Python2使用全局关键字和闭包注入模块范围
tl;dr:是否可以将带有Python2使用全局关键字和闭包注入模块范围,python,scope,closures,inject,Python,Scope,Closures,Inject,tl;dr:是否可以将带有global关键字的函数以注入的global将关闭该模块的方式注入模块?(如何或为什么不?) 带示例的长版本 建议使用setattr方法注入模块名称空间: import foo ## before try: foo.bar() except AttributeError: print 'ok' # expected to print 'ok' ## magic def bar(): pass setattr(foo,'bar',bar)
global
关键字的函数以注入的global
将关闭该模块的方式注入模块?(如何或为什么不?)
带示例的长版本 建议使用
setattr
方法注入模块名称空间:
import foo
## before
try:
foo.bar()
except AttributeError:
print 'ok'
# expected to print 'ok'
## magic
def bar():
pass
setattr(foo,'bar',bar)
## after
foo.bar()
# expected to do nothing (instead of raising an error)
然而,这似乎并不像人们希望使用global
关键字那样有效。例如:
## foo.py
a = 4
def bar():
global a
a = 5
def check(expectation):
global a
assert a == expectation, "%s == %s"%(a,expectation)
a = 4
## rab.py
import foo
foo.bar()
# expected to return and it does
foo.check(5)
print 'bar: ok'
def rab():
global a
a = 6
setattr(foo,'rab',rab)
foo.rab()
# may be expected to return but it raises AssertionError:
foo.check(6)
print 'rab: ok' # never printed
当foo.check
运行时,注入rab
的方式是否可以使该foo.a
变为6
,同时保持原始foo.check
是否可以将带有
global
关键字的函数以注入的global
将关闭该模块的方式注入模块?(怎么做或为什么不?这与您的想法不完全一样,但您可以:
def rab():
foo.a = 6
foo.rab = rab # No need to `setattr` in this simple example
foo.rab()
foo.check(6)
globals
将始终引用模块中定义函数的全局名称空间(无法更改此名称空间)1
1这确实是它唯一明智的行为方式——毕竟,没有什么可以阻止您将
rab
放入多模块名称空间。rab的全局字典已经被加入。您可以在rab.func\u globals
上看到它
该属性为只读,因此无法替换它
您可以在foo
中创建一个新函数,并将代码从rab
推送到其中:)
例如
但不要这样做
type(rab)(rab.func_code, foo.__dict__)
## rab.py
import foo
foo.bar()
# expected to return and it does
foo.check(5)
print 'bar: ok'
def rab():
global a
a = 6
foo.rab = type(rab)(rab.func_code, foo.__dict__)
foo.rab()
# may be expected to return but it raises AssertionError:
foo.check(6)
print 'rab: ok'