私はパーサーを書いていますが、それをデバッグする過程で、どうやらこれは正当な Python であることがわかりました。
for [] in [[]]: print 0
これもそうです(!):
for [][:] in [[]]: print 0
パーサーが混乱するのを責めるつもりはありません...どうやって解釈すればいいのかわからず困っています!
この声明は正確には何を意味するのでしょうか。
私はパーサーを書いていますが、それをデバッグする過程で、どうやらこれは正当な Python であることがわかりました。
for [] in [[]]: print 0
これもそうです(!):
for [][:] in [[]]: print 0
パーサーが混乱するのを責めるつもりはありません...どうやって解釈すればいいのかわからず困っています!
この声明は正確には何を意味するのでしょうか。
実行に関しては、何もありません。
for
ループ自体は空のリストをループするため、反復は行われません。
for []
ループ内の各エントリを 0 変数に割り当てるという手段があるため、これは良いことです。後半はおそらくあなたを困惑させるものです。
ターゲットトークンtoken_list
を使用すると、シーケンス内の値を同じ大きさの変数名のシーケンスに割り当てることができるため、ステートメントは正当です。このタプルのアンパックを呼び出します。以下は、割り当てと削除におけるターゲット リストのより有用な例です。
(a, b, c) = range(3)
del a, b, c
for
ループでも同じことができます:
nested = [[1,2,3], [4,5,6]]
for a, b, c in nested:
print nested
トークンにはタプルとリストの両方を使用できtarget_list
ます。これも合法です。
[a, b] = (1, 2)
ただし、Python では、リストを空にすることができます。したがって、以下は合法ですが、無意味です。
[] = []
最後に、これは次のとおりです。
nested_empty = [[], [], []]
for [] in nested_empty:
pass
ターゲットリストをもっと楽しく:
[][:] = [1, 2, 3]
左側は代入でスライスを使用しています。ドキュメントから:
対象がスライシングの場合: 参照内の一次式が評価されます。変更可能なシーケンス オブジェクト (リストなど) を生成する必要があります。割り当てられたオブジェクトは、同じタイプのシーケンス オブジェクトである必要があります。次に、存在する限り、下限と上限の式が評価されます。デフォルトはゼロとシーケンスの長さです。境界は (小さい) 整数に評価される必要があります。いずれかの境界が負の場合、シーケンスの長さがそれに追加されます。結果の境界は、ゼロとシーケンスの長さの間 (両端を含む) になるようにクリップされます。最後に、シーケンス オブジェクトは、割り当てられたシーケンスのアイテムでスライスを置き換えるように求められます。スライスの長さは、割り当てられたシーケンスの長さとは異なる場合があり、オブジェクトで許可されている場合は、ターゲット シーケンスの長さが変更されます。
したがって、ここではタプルのアンパックを使用しなくなりました。代わりに、左側のリストのセクションを右側のリストに置き換えます。しかし、この例では、左側のリストが無名リスト リテラルであるため、結果として変更されたリストは再び失われます。
しかし、そのような代入は for ループでも有効であるため、次の構文は有効ですが、無意味ではあります。
for [][:] in [range(i) for i in range(10)]: print 0
for [] in [[]]: print 0
[[]] 内の空の iterable ごとに、つまり空のリストを含むリストである 0 を出力することを意味します。これはリストに限定されているだけでなく、すべての iterable をそのリストに入れることができます。たとえば、次のことを試すことができます。
# empty list, empty tuple, empty string, empty unicode
for [] in [[], (), '', unicode()]: print 0
0 を 4 回出力します。
[][:] は [] と同じです。空のリストが返されるので、私の答えは上記と同じです。
for [] in [[]]: print 0
それは以下と同等です:
In [44]: for [x,y] in [[1,2],[3,4],[5,6]]: # or even (x,y) will work
print x,y
....:
....:
1 2
3 4
5 6
しかし、前者は list から値が返されないことを期待しています。つまり、リスト内の値は空であるか、len()
is0
です。
()
有効ではないため、そこでは使用できません。
Pythonでは、次のように割り当てることもできるためです:
In [56]: x,y=[1,2] #this means that the expression on RHS should return two values
# (x,y)=[1,2] or x,y=(1,2) or (x,y)=(1,2) all are valid
In [57]: x
Out[57]: 1
In [58]: y
Out[58]: 2
In [62]: x,y='ab' #assign a to x and b to y
In [63]: x
Out[63]: 'a'
In [64]: y
Out[64]: 'b'
これが私の最善の推測です:
for [] in [[]]
[]
「このリスト[[]]
(空のリスト オブジェクトである要素を 1 つだけ持つリスト) 内の (空のリスト オブジェクト) の各インスタンスに対して、 print 0
.
2 番目のケースでは、リスト全体の一部を取得するだけのすべてのデフォルト値で[:]
呼び出すだけだと思います。slice()
内部的には、たとえばリスト オブジェクトのコピーを作成するなど、何らかの処理が行われる可能性がありますが、この場合の効果は同じである必要があります。
for..in 構造は Python のマニュアルで説明されています。
http://docs.python.org/reference/compound_stmts.html#the-for-statement
in
キーワードの左側に複数の変数を含めることができます
for [i,j] in [(1,2),(3,4),(5,6)]:
print i, j
for [i,j] in [[1,2],[3,4],[5,6]]:
print i, j
マニュアルによると、次のように解釈されます
i,j = (1,2)
最初の繰り返しなど。したがって、反復されたリストには空のリストが唯一の要素として含まれているため、変数の空のリストを作成できます。このループは 0 を 1 回出力します。
あなたが読んでいるパーサーは、自動的に生成されていますか? この種のステートメントは、人間以外のソースによって生成される可能性があります。その目的がわかりません。
次のようなタプルのリストがあるとします。
L = [(1,2), (3,4), (5,6)]
これらのタプルを特別な方法で出力したいとします。
for tup in L:
a = tup[0]
b = tup[1]
if a<b:
print a,b
else:
print b,a
a
しかし、and をb
明示的に の内容に割り当てるのtup
はかなり面倒です。だからあなたはこれをするかもしれません:
for tup in L:
a,b = tup
if a<b:
print a,b
else:
print b,a
しかし、あなたはそれをもっと退屈にすることができます:
for (a,b) in L: # you could also do "for [a,b] in L"
if a<b:
print a,b
else:
print b,a
ここで(a,b)
は、繰り返しによって返される要素に対してパターンが一致します。for ループの最初の実行では、反復によって返される要素は(1,2)
であり、これは に対してパターン マッチングを取得するため、およびに(a,b)
代入1
されます。a
2
b
最初の例では、空のリストを含むリストを繰り返し処理しています。これは、このリスト0
にあるのと同じ数のを印刷しようとしていることを意味します。[]
しかし、それはそれよりも少し複雑です:
3 番目の例のようにパターン マッチを試みると、Python は変数のリスト (またはタプル) と反復子によって返された要素を同時に反復処理し、値が進むにつれて割り当てます。したがって、パターンに変数が含まれていない場合、パターン マッチを実行しようとしている要素も空 (および反復可能) である必要があります。これにより、次の動作が説明されます。
>>> for i in 5: print i
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> for [] in [[], 5]: print 0
...
0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
…そしてこの振る舞いも:
>>> x,y = (2,5,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
>>> for [] in [[], [5]]: print 0
...
0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
さて、2番目の例については、[:]
操作は基本的にそれが呼び出されたリストのコピーを作成するため、元のリストを変更してもコピーは変更されず、その逆も同様です。
>>> L = [1,2,3]
>>> M = L
>>> M[0] = 'a'
>>> print L[0]
'a'
>>> L = [1,2,3]
>>> M = L[:]
>>> M[0] = 'a'
>>> print L[0]
1
したがって、 を呼び出すとき[][:]
は、新しい空のリストを作成するだけです。これは、最初の例の説明と同じように機能します