是否有任何python大师能够解释为什么这段代码不起作用:
def f(code_str):
exec(code_str)
code = """
g = 5
x = [g for i in range(5)]
"""
f(code)
Run Code Online (Sandbox Code Playgroud)
错误:
Traceback (most recent call last):
File "py_exec_test.py", line 9, in <module>
f(code)
File "py_exec_test.py", line 2, in f
exec(code_str)
File "<string>", line 3, in <module>
File "<string>", line 3, in <listcomp>
NameError: name 'g' is not defined
Run Code Online (Sandbox Code Playgroud)
虽然这个工作正常:
code = """
g = 5
x = [g for i in range(5)]
"""
exec(code)
Run Code Online (Sandbox Code Playgroud)
我知道它与locals和globals有关,就好像我从我的主范围传递exec函数locals和globals它工作正常,但我不完全理解发生了什么.
这可能是Cython的一个错误吗?
编辑:尝试使用python 3.4.0和python 3.4.3
在我发布这个问题之前,我已经搜索了SO,希望这不是一个重复的问题.
def print_me():
a_list = range(1, 10)
for idx, aa in enumerate(a_list):
pass
print(idx)
if __name__ == '__main__' : print_me()
Run Code Online (Sandbox Code Playgroud)
输出如下:
8
我是从C++世界来的,idx当代码在for循环的一边时,无法弄清楚为什么仍然在范围内?
谢谢
在给定脚本中的多个for循环中重复使用相同的迭代变量名称被认为是不好的做法吗?
例如,
for url in urls1:
print url
for url in urls2:
print url
for url in urls3:
print url
Run Code Online (Sandbox Code Playgroud)
我知道url变量的范围不限于for循环,因此url在for循环之外使用变量时可能会变得混乱并且可能更难以理解.但我很好奇,有没有"最好"的做法?我应该使用像"url1","url2"这样的约定吗?或者我是否在思考这个问题,而这只是为了让它更容易理解?
在Effective Python一书中,作者建议使用赋值表达式来避免理解中的冗余,例如:
def fun(i):
return 2 * i
result = {x: y for x in [0, 1, 2, 3] if (y := fun(x)) > 3}
Run Code Online (Sandbox Code Playgroud)
代替
result = {x: fun(x) for x in [0, 1, 2, 3] if fun(x) > 3}
Run Code Online (Sandbox Code Playgroud)
result有价值{2: 4, 3: 6}。
作者指出
如果推导式在推导式的值部分使用海象运算符并且没有条件,它会将循环变量泄漏到包含范围中。[...] 最好不要泄漏循环变量,因此我建议仅在推导式的条件部分使用赋值表达式。
然而,在上面的例子中, y在程序结束时设置为 6。因此,赋值表达式中的变量泄漏了,尽管它是在条件中定义的。
列表推导式也会发生同样的事情:
>>> _ = [(x, leak) for x in range(4) if (leak := 2 * x) > 3]
>>> leak
6
Run Code Online (Sandbox Code Playgroud)
甚至对于生成器表达式:
>>> …Run Code Online (Sandbox Code Playgroud) 看看下面这段代码:
class a:
s = 'python'
b = ['p', 'y']
c = [x for x in s]
Run Code Online (Sandbox Code Playgroud)
输出:
>>> a.c
['p', 'y', 't', 'h', 'o', 'n']
Run Code Online (Sandbox Code Playgroud)
但当我试图限制列表时,如果:
class a:
s = 'python'
b = ['p', 'y']
c = [x for x in s if x in b]
Run Code Online (Sandbox Code Playgroud)
显示以下异常:
Traceback (most recent call last):
File "<pyshell#22>", line 1, in <module>
class a:
File "<pyshell#22>", line 4, in a
c = [x for x in s if x in b]
File "<pyshell#22>", …Run Code Online (Sandbox Code Playgroud) 为什么eval在字典理解中访问函数参数会失败?
ARGS1 = ('a1', 'b1')
def foo1(a1, b1):
return {arg:eval(arg) for arg in ARGS1}
print foo1("A1", "B1") # NameError: name 'a1' is not defined
Run Code Online (Sandbox Code Playgroud)
列表理解中同样的事情很好:
ARGS2 = ('a2', 'b2')
def foo2(a2, b2):
return [eval(arg) for arg in ARGS2]
print foo2("A2", "B2") # OK, print: ['A2', 'B2']
Run Code Online (Sandbox Code Playgroud)
没有功能它也很好用:
ARGS3 = ('a3', 'b3')
a3, b3 = ("A3", "B3")
print {arg:eval(arg) for arg in ARGS3} # OK, print: ['A3', 'B3']
Run Code Online (Sandbox Code Playgroud)
或者如果定义了全局变量:
ARGS4 = ('a4', 'b4')
a4, b4 = ("A4", "B4")
def …Run Code Online (Sandbox Code Playgroud) 在列表理解中使用闭包时,我发现了这个:
xs = [1, 2, 3]
fs = [lambda: _ for _ in xs]
vs = [_() for _ in fs]
print vs # [<function <lambda> at 0x020324B0>, <function <lambda> at 0x020D6AB0>, <function <lambda> at 0x020D6AF0>]
print vs[0] # <function <lambda> at 0x020324B0>
print vs[0]() # <function <lambda> at 0x020D6AF0>
print vs[0]()() # <function <lambda> at 0x020D6AF0>
print vs[0]()()() # <function <lambda> at 0x020D6AF0>
Run Code Online (Sandbox Code Playgroud)
不应该vs包含ints而不是lambdas?
但是如果我们在两个列表推导中使用不同的名称,它将按预期工作:
xs = [1, 2, 3]
fs = [lambda: …Run Code Online (Sandbox Code Playgroud) 作为另一种体验的一部分,我在列表理解中遇到了一个问题.为了简单起见,如果我尝试以下代码:
m = [ k**2 for k in range(7)]
print m
[0, 1, 4, 9, 16, 25, 36]
print k
6
Run Code Online (Sandbox Code Playgroud)
我有这样的字符串
PARAMS = 'TEST = xy; TEST2= klklk '
Run Code Online (Sandbox Code Playgroud)
我想分开两次,一次在";" 第二个在"="然后把它放在一个字典中.
我可以用这一行做到这一点:
dict(item.split("=") for item in PARAMS.split(";"))
Run Code Online (Sandbox Code Playgroud)
得到:
{' TEST2': ' klklk ', 'TEST ': ' xy'}
Run Code Online (Sandbox Code Playgroud)
我现在还希望在将它们放入dict之前去除键和值.有没有一种优雅的方式在python的一行中做到这一点?
在以下 Python 代码中:
keyboards = [3, 1]
drivers = [5, 2, 8]
upper_limit = 10
sums = [k + d for k in keyboards for d in drivers if (k + d) <= upper_limit]
Run Code Online (Sandbox Code Playgroud)
我想将 的结果存储k+d在列表理解中,以便它可以在列表理解中引用。在 Python3 中可能吗?
我知道我们可以做到以下几点:
sums = []
for k in keyboards:
for d in drivers:
s = k + d
if s <= upper_limit:
sums.append(s)
Run Code Online (Sandbox Code Playgroud)
但我希望避免 append 的副作用操作。
在阅读官方教程时,我遇到了这个例子:
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
我无法理解这一点,所以我做了一些实验:
>>> [num for elem in vec]
[9, 9, 9]
>>> [num for elem in (vec for num in elem)]
[9, 9, 9]
Run Code Online (Sandbox Code Playgroud)
而我现在更迷茫了!
我应该按什么顺序阅读列表理解?
我确定我没有num在任何地方定义值为 9 的变量。
python
Run Code Online (Sandbox Code Playgroud)
输出:
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" …Run Code Online (Sandbox Code Playgroud) 是的.这发生了.当我心不在焉地把一个索引放在变量中时.解释(它?).在一般情况下发生了什么以及它的用例是什么?
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
Traceback (most recent call last):
File "<pyshell#209>", line 1, in <module>
[q for q[0] in [range(10),range(10,-1,-1)]]
NameError: name 'q' is not defined
>>> [q for q in [range(10),range(10,-1,-1)]]
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]
>>> [q for q[0] in [range(10),range(10,-1,-1)]]
[[[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], 9, 8, 7, 6, 5, 4, 3, …Run Code Online (Sandbox Code Playgroud) python ×12
closures ×2
arguments ×1
python-2.7 ×1
python-3.x ×1
python-assignment-expression ×1
python-exec ×1
scope ×1
split ×1
strip ×1