在“中捕获变量”;“评估”;用Python
我在理解Python中“eval()”和“exec”的语义时遇到困难。(此问题中的所有代码在Python 2.7.8和Python 3.4.2中的行为方式相同)。“评估”一词的意思是: 如果同时省略[locals and globals],则执行表达式 在调用eval()的环境中 “exec”也有类似的语言。我显然不理解这句话,因为我希望下面的程序定义的四个函数也能做同样的事情在“中捕获变量”;“评估”;用Python,python,python-2.7,eval,python-3.4,Python,Python 2.7,Eval,Python 3.4,我在理解Python中“eval()”和“exec”的语义时遇到困难。(此问题中的所有代码在Python 2.7.8和Python 3.4.2中的行为方式相同)。“评估”一词的意思是: 如果同时省略[locals and globals],则执行表达式 在调用eval()的环境中 “exec”也有类似的语言。我显然不理解这句话,因为我希望下面的程序定义的四个函数也能做同样的事情 def h(x): ls = locals() exec('def i(y): return (w,
def h(x):
ls = locals()
exec('def i(y): return (w, x, y)', globals(), ls)
i = ls['i']
def j(y): return (w, x, y)
k = eval('lambda y: (w, x, y)')
l = lambda y: (w, x, y)
return i, j, k, l
w = 1
i, j, k, l = h(2)
他们没有
>>> i(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in i
NameError: name 'x' is not defined
>>> j(3)
(1, 2, 3)
>>> k(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: name 'x' is not defined
>>> l(3)
(1, 2, 3)
输出:
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
25 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `k`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `l`:
27 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
For reference, this is `h`:
22 0 LOAD_NAME 0 (locals)
3 CALL_FUNCTION 0
6 STORE_FAST 1 (ls)
23 9 LOAD_CONST 1 ('def i(y): return (w, x, y)')
12 LOAD_NAME 1 (globals)
15 CALL_FUNCTION 0
18 LOAD_FAST 1 (ls)
21 EXEC_STMT
24 22 LOAD_FAST 1 (ls)
25 LOAD_CONST 2 ('i')
28 BINARY_SUBSCR
29 STORE_FAST 2 (i)
25 32 LOAD_CLOSURE 0 (x)
35 BUILD_TUPLE 1
38 LOAD_CONST 3 (<code object j at 0x7ffc3843c030, file "test.py", line 25>)
41 MAKE_CLOSURE 0
44 STORE_FAST 3 (j)
26 47 LOAD_NAME 2 (eval)
50 LOAD_CONST 4 ('lambda y: (w, x, y)')
53 CALL_FUNCTION 1
56 STORE_FAST 4 (k)
27 59 LOAD_CLOSURE 0 (x)
62 BUILD_TUPLE 1
65 LOAD_CONST 5 (<code object <lambda> at 0x7ffc3843c3b0, file "test.py", line 27>)
68 MAKE_CLOSURE 0
71 STORE_FAST 5 (l)
28 74 LOAD_FAST 2 (i)
77 LOAD_FAST 3 (j)
80 LOAD_FAST 4 (k)
83 LOAD_FAST 5 (l)
86 BUILD_TUPLE 4
89 RETURN_VALUE
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: global name 'x' is not defined
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_CONST 1 (2)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
输出:
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
25 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `k`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `l`:
27 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
For reference, this is `h`:
22 0 LOAD_NAME 0 (locals)
3 CALL_FUNCTION 0
6 STORE_FAST 1 (ls)
23 9 LOAD_CONST 1 ('def i(y): return (w, x, y)')
12 LOAD_NAME 1 (globals)
15 CALL_FUNCTION 0
18 LOAD_FAST 1 (ls)
21 EXEC_STMT
24 22 LOAD_FAST 1 (ls)
25 LOAD_CONST 2 ('i')
28 BINARY_SUBSCR
29 STORE_FAST 2 (i)
25 32 LOAD_CLOSURE 0 (x)
35 BUILD_TUPLE 1
38 LOAD_CONST 3 (<code object j at 0x7ffc3843c030, file "test.py", line 25>)
41 MAKE_CLOSURE 0
44 STORE_FAST 3 (j)
26 47 LOAD_NAME 2 (eval)
50 LOAD_CONST 4 ('lambda y: (w, x, y)')
53 CALL_FUNCTION 1
56 STORE_FAST 4 (k)
27 59 LOAD_CLOSURE 0 (x)
62 BUILD_TUPLE 1
65 LOAD_CONST 5 (<code object <lambda> at 0x7ffc3843c3b0, file "test.py", line 27>)
68 MAKE_CLOSURE 0
71 STORE_FAST 5 (l)
28 74 LOAD_FAST 2 (i)
77 LOAD_FAST 3 (j)
80 LOAD_FAST 4 (k)
83 LOAD_FAST 5 (l)
86 BUILD_TUPLE 4
89 RETURN_VALUE
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: global name 'x' is not defined
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_CONST 1 (2)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
输出:
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
25 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `k`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `l`:
27 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
For reference, this is `h`:
22 0 LOAD_NAME 0 (locals)
3 CALL_FUNCTION 0
6 STORE_FAST 1 (ls)
23 9 LOAD_CONST 1 ('def i(y): return (w, x, y)')
12 LOAD_NAME 1 (globals)
15 CALL_FUNCTION 0
18 LOAD_FAST 1 (ls)
21 EXEC_STMT
24 22 LOAD_FAST 1 (ls)
25 LOAD_CONST 2 ('i')
28 BINARY_SUBSCR
29 STORE_FAST 2 (i)
25 32 LOAD_CLOSURE 0 (x)
35 BUILD_TUPLE 1
38 LOAD_CONST 3 (<code object j at 0x7ffc3843c030, file "test.py", line 25>)
41 MAKE_CLOSURE 0
44 STORE_FAST 3 (j)
26 47 LOAD_NAME 2 (eval)
50 LOAD_CONST 4 ('lambda y: (w, x, y)')
53 CALL_FUNCTION 1
56 STORE_FAST 4 (k)
27 59 LOAD_CLOSURE 0 (x)
62 BUILD_TUPLE 1
65 LOAD_CONST 5 (<code object <lambda> at 0x7ffc3843c3b0, file "test.py", line 27>)
68 MAKE_CLOSURE 0
71 STORE_FAST 5 (l)
28 74 LOAD_FAST 2 (i)
77 LOAD_FAST 3 (j)
80 LOAD_FAST 4 (k)
83 LOAD_FAST 5 (l)
86 BUILD_TUPLE 4
89 RETURN_VALUE
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: global name 'x' is not defined
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_CONST 1 (2)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
但是,我不想假设“x”可以无损地转换为字符串并返回。在以下示例中,尝试失败:
k = h(lambda: "something")
k = h(open('some_file', 'w'))
cell = ["Wrong value"]
k = h(cell)
cell[0] = "Right value"
k(3)
失败3
由于Python正在寻找全局变量,一个明显的尝试是将“x”作为全局变量传递:
def h(x):
my_globals = {'w': w, 'x': x}
return eval('lambda y: (w, x, y)', my_globals)
k = h(2)
dis(k)
w = 1
k(3)
输出:
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
25 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `k`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `l`:
27 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
For reference, this is `h`:
22 0 LOAD_NAME 0 (locals)
3 CALL_FUNCTION 0
6 STORE_FAST 1 (ls)
23 9 LOAD_CONST 1 ('def i(y): return (w, x, y)')
12 LOAD_NAME 1 (globals)
15 CALL_FUNCTION 0
18 LOAD_FAST 1 (ls)
21 EXEC_STMT
24 22 LOAD_FAST 1 (ls)
25 LOAD_CONST 2 ('i')
28 BINARY_SUBSCR
29 STORE_FAST 2 (i)
25 32 LOAD_CLOSURE 0 (x)
35 BUILD_TUPLE 1
38 LOAD_CONST 3 (<code object j at 0x7ffc3843c030, file "test.py", line 25>)
41 MAKE_CLOSURE 0
44 STORE_FAST 3 (j)
26 47 LOAD_NAME 2 (eval)
50 LOAD_CONST 4 ('lambda y: (w, x, y)')
53 CALL_FUNCTION 1
56 STORE_FAST 4 (k)
27 59 LOAD_CLOSURE 0 (x)
62 BUILD_TUPLE 1
65 LOAD_CONST 5 (<code object <lambda> at 0x7ffc3843c3b0, file "test.py", line 27>)
68 MAKE_CLOSURE 0
71 STORE_FAST 5 (l)
28 74 LOAD_FAST 2 (i)
77 LOAD_FAST 3 (j)
80 LOAD_FAST 4 (k)
83 LOAD_FAST 5 (l)
86 BUILD_TUPLE 4
89 RETURN_VALUE
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: global name 'x' is not defined
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_CONST 1 (2)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
此尝试被中断,因为它过早读取“w”的值:
w = "Wrong value"
k = h(2)
w = "Right value"
k(3)
成功1
我最终找到了一种可行的方法,但我真的不喜欢:
def h(x):
return eval('lambda x: lambda y: (w, x, y)')(x)
k = h(2)
dis(k)
w = 1
k(3)
输出:
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
25 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `k`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `l`:
27 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
For reference, this is `h`:
22 0 LOAD_NAME 0 (locals)
3 CALL_FUNCTION 0
6 STORE_FAST 1 (ls)
23 9 LOAD_CONST 1 ('def i(y): return (w, x, y)')
12 LOAD_NAME 1 (globals)
15 CALL_FUNCTION 0
18 LOAD_FAST 1 (ls)
21 EXEC_STMT
24 22 LOAD_FAST 1 (ls)
25 LOAD_CONST 2 ('i')
28 BINARY_SUBSCR
29 STORE_FAST 2 (i)
25 32 LOAD_CLOSURE 0 (x)
35 BUILD_TUPLE 1
38 LOAD_CONST 3 (<code object j at 0x7ffc3843c030, file "test.py", line 25>)
41 MAKE_CLOSURE 0
44 STORE_FAST 3 (j)
26 47 LOAD_NAME 2 (eval)
50 LOAD_CONST 4 ('lambda y: (w, x, y)')
53 CALL_FUNCTION 1
56 STORE_FAST 4 (k)
27 59 LOAD_CLOSURE 0 (x)
62 BUILD_TUPLE 1
65 LOAD_CONST 5 (<code object <lambda> at 0x7ffc3843c3b0, file "test.py", line 27>)
68 MAKE_CLOSURE 0
71 STORE_FAST 5 (l)
28 74 LOAD_FAST 2 (i)
77 LOAD_FAST 3 (j)
80 LOAD_FAST 4 (k)
83 LOAD_FAST 5 (l)
86 BUILD_TUPLE 4
89 RETURN_VALUE
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: global name 'x' is not defined
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_CONST 1 (2)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
(1, 2, 3)
特别是,如果我不知道传递给“eval”的字符串捕获的本地变量的完整列表,这将变得非常痛苦
你能做得更好吗
更新2014-12-25
失败4
为了寻找创建局部变量“x”的更多方法,我尝试了以下方法:
def h(x):
ls = locals()
exec('x = x\ndef i(y): return (w, x, y)', globals(), ls)
exec('_ = x\ndef j(y): return (w, x, y)', globals(), ls)
return ls['i'], ls['j'], ls['_'], ls['x']
i, j, check1, check2 = h(2)
assert check1 == 2
assert check2 == 2
w = 1
print("This is `i`:")
dis(i)
print("This is `j`:")
dis(j)
print("i(3) = %r" % (i(3),))
print("j(3) = %r" % (j(3),))
“x”的额外赋值无效。断言验证“x”在局部变量字典中,但lambdas没有捕获它。以下是输出:
This is `i`:
2 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
2 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
i(3) = (1, 2, 3)
barley's x = outer arg
barley's y = this string
barley's x = modified x
barley's y = new arg
barley's x = modified x
barley's y = doesn't see the re-mod.
对“i”和“j”的调用都崩溃了,抱怨没有全局变量“x”
成功2
[编辑2014-12-29:这仅在Python 3上成功。]
创建局部变量的另一种方法如下:
def h(x):
i = eval('[lambda y: (w, x, y) for x in [x]][0]')
j = eval('[lambda y: (w, x, y) for _ in [x]][0]')
return i, j
i, j = h(2)
w = 1
print("This is `i`:")
dis(i)
print("This is `j`:")
dis(j)
print("i(3) = %r" % (i(3),))
print("j(3) = %r" % (j(3),))
奇怪的是,在这种情况下,对“x”的额外赋值确实会产生影响。这确实有效,即“i”与“j”不同。以下是输出:
This is `i`:
2 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
2 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
i(3) = (1, 2, 3)
barley's x = outer arg
barley's y = this string
barley's x = modified x
barley's y = new arg
barley's x = modified x
barley's y = doesn't see the re-mod.
对“j”的调用崩溃,抱怨没有全局“x”,但“i”按预期工作并具有正确的字节码
为什么这能起作用,而上面的“失败4”不能?确定是否可以捕获本地“x”的规则是什么?这种设计的历史是什么?(这似乎很荒谬!)我认为您希望创建的函数继承创建它们的函数的本地环境,同时也继承(创建它们的函数的)真实的全局环境。这就是为什么你不喜欢他们把x称为全局的,对吧 下面将围绕所需函数创建一个“包装器”函数,所有函数都位于同一exec字符串中。当您调用或重新调用包装器(创建新的包装闭包)时,将传入创建函数的局部变量的值 代码对在本地上下文中创建的新变量很敏感。要确保函数名和包装器名都是已知的,并且都有值,这会遇到一些麻烦
def wrap_f(code, gs, ls, wrapper_name, function_name):
ls[function_name] = ls[wrapper_name] = None
arglist = ",".join(ls.keys())
wrapcode = """
def {wrapper_name}({arglist}):
{code}
return {function_name}
""".format(wrapper_name=wrapper_name, arglist=arglist,
code=code, function_name=function_name)
exec(wrapcode, gs, ls)
wrapper = ls[wrapper_name]
return wrapper, wrapper(**ls)
所以,为了回答最初的问题,这个代码
def h(x):
mcode = " def m(y): return (w, x, y)" # must be indented 4 spaces.
mwrap, m = wrap_f(mcode, globals(), locals(), "mwrap", "m")
return m
w = 1
m = h(2)
print m(3)
…生成此输出:
(1, 2, 3)
此示例显示了当creator函数中的局部变量发生更改时应执行的操作:
def foo(x):
barleycode = """
def barley(y):
print "barley's x =", x
print "barley's y =", y
"""
barleywrap, barley = wrap_f(barleycode, globals(), locals(),
"barleywrap", "barley")
barley("this string")
print
x = "modified x"
barley = barleywrap(**locals())
barley("new arg")
print
x = "re-modified x"
barley("doesn't see the re-mod.")
x = "the global x"
foo("outer arg")
这将产生以下输出:
This is `i`:
2 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
2 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `i`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_DEREF 0 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
This is `j`:
1 0 LOAD_GLOBAL 0 (w)
3 LOAD_GLOBAL 1 (x)
6 LOAD_FAST 0 (y)
9 BUILD_TUPLE 3
12 RETURN_VALUE
i(3) = (1, 2, 3)
barley's x = outer arg
barley's y = this string
barley's x = modified x
barley's y = new arg
barley's x = modified x
barley's y = doesn't see the re-mod.
我不确定我自己是否完全明白,但我会尽最大努力: 我猜当你运行eval/exec python时,你不知道它在函数中,我真的不知道为什么。 我将尝试使用如下格式字符串
k = eval("lambda y: (w, {0}, y)".format(x))
不过我不确定这东西是否管用。
另外,为什么需要以这种方式使用eval和exec?我将分享我自己的理解,即python为什么会这样做
k = eval("lambda y: (w, {0}, y)".format(x))
Lambda如何捕获引用
每次使用不在参数列表中的变量时,python都会为其创建一个闭包。比如说
y
def h(x):
l =lambda y: (w, x,y)
创建一个捕获x的闭包,您可以通过访问
l.__closure__
这将向您显示x是与函数创建一起存储的。
但是,y不是与函数一起存储的,因为它被定义为全局变量
类定义
当运行A.f()
因为python将在没有定义c
的全局命名空间中查找c
原因
说
如果exec获得两个单独的对象,即全局对象和局部对象,则代码
将像嵌入到类定义中一样执行
这说明了为什么lambda没有捕获本地名称空间中的变量
变通
i
和j
不是本地人。它们是封闭的。Python在编译时确定闭包,但在eval()
中生成此类闭包的唯一方法是您已经发现的方式。您无法以任何其他方式创建闭包。令人惊讶的是,无法捕获传入“locals”的变量。为什么会这样?因为关闭需要更多的脚手架;变量的生存期延长到函数的生存期之外,而常规的局部变量在那里是不行的;列表理解(以及dict和set理解和生成器表达式)也允许您在单个表达式中创建父范围。您还可以使用默认参数hack。在PEP227将词法作用域添加到Python 2.1之前,这是很常见的。您可以使用3.x纯关键字参数使其更加可靠:k=eval('lambda y,*,x=x:(w,x,y))
“我认为您希望创建的函数继承创建它们的函数的本地环境,也继承(创建它们的函数的)真实全局环境。”这就是为什么你不喜欢他们把x称为全局变量,对吗?“我接受你的观点,我不需要知道‘传递给“eval”的字符串捕获的全部局部变量列表’。我只需要知道其中的一个超集,“locals().keys()”就可以了。按照我的说法,你不需要知道需要哪些,你只需要拥有所有可能需要的。这些变量名都会进入st的“barleywrap”部分