Ree*_*ece 12 python python-2.7 python-3.x python-3.5
在下面的代码中,该mc分配在Python 2和3中正常工作.
cc在类中使用相同列表推导的赋值在Python 2中有效,但在Python 3中失败.
什么解释了这种行为?
ml1 = "a b c".split()
ml2 = "1 2 3".split()
mc = [ i1 + i2 for i1 in ml1 for i2 in ml2 ]
class Foo(object):
cl1 = ml1
cl2 = ml2
cc1 = [ i1 for i1 in cl1 ]
cc2 = [ i2 for i2 in cl2 ]
cc = [ i1 + i2 for i1 in cl1 for i2 in cl2 ]
print("mc = ", mc)
foo = Foo()
print("cc = ", foo.cc)
Run Code Online (Sandbox Code Playgroud)
我明白了:
(default-3.5) snafu$ python2 /tmp/z.py
('mc = ', ['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3'])
('cc = ', ['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3'])
(default-3.5) snafu$ python3 /tmp/z.py
Traceback (most recent call last):
File "/tmp/z.py", line 5, in <module>
class Foo(object):
File "/tmp/z.py", line 11, in Foo
cc = [ i1 + i2 for i1 in cl1 for i2 in cl2 ]
File "/tmp/z.py", line 11, in <listcomp>
cc = [ i1 + i2 for i1 in cl1 for i2 in cl2 ]
NameError: name 'cl2' is not defined
Run Code Online (Sandbox Code Playgroud)
为什么cl2没有定义类变量?请注意,cc2分配工作正常cc1.交换cl1和cl2理解表明第二个循环是触发异常的循环,而不是cl2本身.)
版本:
(default-3.5) snafu$ python2 --version
Python 2.7.11+
(default-3.5) snafu$ python3 --version
Python 3.5.1+
Run Code Online (Sandbox Code Playgroud)
在Python 3中,列表推导有自己的范围,它遵循与函数范围相同的规则.您知道类的方法如何不自动查看变量查找的类作用域内部吗?
class Example:
var = 1
def this_fails(self):
print(var)
Example().this_fails() # NameError
Run Code Online (Sandbox Code Playgroud)
这同样适用于嵌套在类范围内的任何函数范围,包括列表推导的范围.cl2列表理解内部的查找绕过了类范围并直接进入全局变量.它有效地工作如下:
class Foo(object):
...
def make_cc(outer_iterable):
result = []
for i1 in outer_iterable:
for i2 in cl2: # This fails
result.append(i1 + i2)
return result
cc = make_cc(cl1) # cl1 is evaluated outside the comprehension scope, for reasons
Run Code Online (Sandbox Code Playgroud)
请注意,cl1查找工作正常,因为它发生在类范围内,在理解之外,尽管语法嵌套在理解中.当Python引入genexps时,他们做出了这个决定,因为它更早地捕获了一些常见的genexp错误.这也是为什么在cc1和cc2list解析的工作; 他们唯一使用类级变量的是外部(仅)for可迭代.
在类语句中使用comprehensions和generator表达式是一团糟.它不应该,但确实如此.坚持使用常规循环,或者在类声明之外运行理解,这样语义就更明显了.
| 归档时间: |
|
| 查看次数: |
528 次 |
| 最近记录: |