我不小心写了这样的代码:
foo = [42]
k = {'c': 'd'}
for k['z'] in foo: # Huh??
print k
Run Code Online (Sandbox Code Playgroud)
但令我惊讶的是,这不是语法错误.相反,它打印{'c': 'd', 'z': 42}.
我的猜测是代码翻译成字面意思:
i = iter(foo)
while True:
try:
k['z'] = i.next() # literally translated to assignment; modifies k!
print k
except StopIteration:
break
Run Code Online (Sandbox Code Playgroud)
但是......为什么语言允许这样做?我希望在for-stmt的目标表达式中只允许使用单个标识符和标识符元组.是否存在实际有用的情况,而不仅仅是一个奇怪的问题?
因此,在测验中,我提出了执行该代码块会产生什么结果的问题(下图)。
a = [0, 1, 2, 3]
for a[0] in a:
print(a[0])
Run Code Online (Sandbox Code Playgroud)
我选择了错误,但令我惊讶的是,它实际上有效并且能够打印列表中的所有元素。但如何呢?
首先,获取变量的元素(通常是 i)正在隐藏实际变量,除此之外我们正在获取数字内的第一个元素,那么它是如何工作的。
在CPython 2.7.10和3.4.3以及PyPy 2.6.0(Python 2.7.9)中,在for循环中使用表达式(或它们的某些子集)作为名称列表显然是合法的.这是一个典型的for循环:
>>> for a in [1]: pass
...
>>> a
1
Run Code Online (Sandbox Code Playgroud)
但您也可以使用对象中的属性:
>>> class Obj(object): pass
...
>>> obj = Obj()
>>> for obj.b in [1]: pass
...
>>> obj.b
1
Run Code Online (Sandbox Code Playgroud)
你甚至可以使用表达式中的属性:
>>> for Obj().c in [1]: pass
...
Run Code Online (Sandbox Code Playgroud)
但并非所有表达式都可行:
>>> for (True and obj.d) in [1]: pass
...
File "<stdin>", line 1
SyntaxError: can't assign to operator
Run Code Online (Sandbox Code Playgroud)
但只要属性在外面,他们就会这样做吗?
>>> for (True and obj).e in [1]: pass
...
>>> obj.e
1
Run Code Online (Sandbox Code Playgroud)
或者可以分配什么?
>>> for {}['f'] in [1]: …Run Code Online (Sandbox Code Playgroud) 我在谷歌搜索时发现了这个问题,但不明白它是怎么发生的?
a = [0, 1, 2, 3]
for a[-1] in a:
print(a[-1])
Run Code Online (Sandbox Code Playgroud)
结果:
0 1 2 2
现在,如果我再次打印:
a
[0, 1, 2, 2]
Run Code Online (Sandbox Code Playgroud)
另一个类似的例子:
让 a 成为原始列表,即 [0,1,2,3]
现在,让我们运行另一个 for 循环,但像这样:
for a[0] in a:
print(a[0])
Run Code Online (Sandbox Code Playgroud)
这次的结果是:
0 1 2 3
但再次打印:
[3,1,2,3]
Run Code Online (Sandbox Code Playgroud)
所以,我有两个问题:
1) 在这两种情况下,原始列表是如何更新的?
2)第一种情况下的结果的解释是什么,即循环的负索引?