リストがあります、たとえば、a = [[1,2],[3,4],[5,6]]
文字列'a'
をリストa
の各アイテムに追加します。
私が使うとき:
a = [x.append('a') for x in a]
[None,None,None]
を返します。
しかし、私が使用する場合:
a1 = [x.append('a') for x in a]
それからそれは奇妙なことをします。
a
、ただしa1
は[[1,2,'a'],[3,4,'a'],[5,6,'a']]
ではありません。
最初の呼び出しで[None, None, None]
が返される理由も、2番目の呼び出しがa1
ではなくa
で変更される理由もわかりません。
list.append
はリスト自体を変更し、None
を返します。リスト内包表記は結果を保存するためのものであり、元のリストを変更するだけの場合、この場合は必要ありません。
>>> x = [[1, 2], [3, 4], [5, 6]]
>>> for sublist in x:
... sublist.append('a')
...
>>> x
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']]
他の人が言ったように、append
はリスト自体を変更するので、変数に割り当てるべきではありません。それを実行するとデータが変更され、それを指しているすべての人が効果的に更新されます。
しかし、既存のオブジェクトを変更する際に機能的な方法で(新しいオブジェクトを構築するのではなく、この場合はa=[x + ['a'] for x in a]
を使用して)やりたいときに使用するトリックがあります、または具体的にはx + ['a']
)。
だから、あなたが十分に勇気があるなら、あなたもこれをすることができます:
>>> a=[[1,2],[3,4],[5,6]]
>>> a=[x.append('a') or x for x in a]
>>> a
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']]
これは、append
がNone
を返し、or
がx
である真理値の値を探し続けるため、機能します。 is(これは、少なくとも追加されたlist
です)。
なぜこれが必要なのですか?
リストがあり、そのメンバーの一部を新しいリストに挿入し、それに応じて参照を更新するとします。
だからあなたはリストall
を持っています:
>>> all = [[], [], [], []]
その一部が挿入され、新しいリストx
に更新されます。
>>> x = [i.append('x') or i for i in all[:2]]
>>> x
[['x'], ['x']]
all
の一部も挿入され、リストy
に更新されます。
>>> y = [i.append('y') or i for i in all[1:3]]
all
が更新されました:
>>> all
[['x'], ['x', 'y'], ['y'], []]
ただし、x
も更新されます。
>>> x
[['x'], ['x', 'y']]
そしてy
は期待通りに生成されます:
>>> y
[['x', 'y'], ['y']]
全体として、単純なタスクの場合、明示的に更新するfor
ループを使用することをお勧めします。これはPythonicと見なされているものです。
技術的には、リストクラスにアクセスできる場合、これを関数にすることができます。
def more_functional_append(self, x):
self.append(x)
return self
append
は、リストを変更し(純粋な関数型プログラミングは不変オブジェクトのみを持つ)、他のアクション(関数)に渡す結果を返さないため、あまり機能的ではありません。関数型プログラミングの概念を使用すると、「ジョブセキュリティ」または「不良コード」としても知られる、誰も読めない大きな大きな1行を作成できます。最初のケースでは、[None, None, None]
がNone
を返すため、list.append
が返されます。これがリストに格納されているものです。
2番目のケースでは、リストが変更可能であり、値を追加するたびに元のリストが変更されます。
必要なのは、+
などの非インプレース追加演算子です。つまり、[x + ['a'] for x in a]
です。
(これはMike Grahamとsykoraによる回答の組み合わせです):
値をインプレースで変更するだけの場合は、リスト内包ではなく、通常のforループを試してください。
for sublist in a:
sublist.append('a')
あなたが一人のままにして、結果をa1に入れたい場合:
a1 = [sublist + ['a'] for sublist in a]
彼らが説明したように、append
はリストを変更しますが、Noneを返しますが、+
はリストをそのままにしますが、新しく追加されたリストを返します。
次のように、リスト内包内でリスト追加を使用できます。
a = [x + ['a'] for x in a]
これにより、aに望ましい結果が得られます。この場合、ループの前に変数名に['a']を割り当てることでより効率的にすることができますが、それは何をしたいかによって異なります。
出て a =
とa
の副作用を使用:
[x.append('a') for x in a]
print a
リスト内包の最初の値の割り当てで属性エラー、「NoneType」オブジェクトに属性「append」がないため、リストaにNone(s)がロードされる理由を説明できます。コンソールでエラーをスローするために、リスト内包表記の変数として、また反復子としてxを使用しました。
Traceback (most recent call last):
x = [x.append('a') for x in a]
AttributeError: 'NoneType' object has no attribute 'append'
次に、xのaに戻したところ、同じエラーが発生しました。
Traceback (most recent call last):
a = [x.append('a') for x in a]
AttributeError: 'NoneType' object has no attribute 'append'