无法在函数中动态创建具有局部作用域的类,但在顶层工作。
如何在正确的命名空间范围内动态创建类。
我正在尝试动态创建添加到调用者名称空间的类。
这样我就可以做到以下几点。
import creator
creator.make('SomeClass')
print "SomeClass :", SomeClass
当在顶级添加动态类但在中尝试在函数内执行相同操作时,这可以使用,这样创建的类只有本地范围,它不起作用
我看到 hack 在放入函数内部时会起作用,但会消失。
以下代码显示问题显然会比显示的更多creator.py
。
# creator.py
import inspect
def make(classname):
t = type(classname, (object,), { })
frame = inspect.currentframe()
print "WILL make() - callers locals :", frame.f_back.f_locals.keys()
frame.f_back.f_locals[classname] = t
print "DID make() - callers locals :", frame.f_back.f_locals.keys()
return t
# example.py
import creator
print "WILL __main__ - locals :", locals().keys()
creator.make('SomeClass')
print "DID __main__ - locals :", locals().keys()
print "SomeClass :", SomeClass
print "-" * 80
def closed():
# This hack helps
# https://stackoverflow.com/a/1549221/1481060
# exec ''
class ClosedClass: pass
print "WILL closed() - locals :", locals().keys()
creator.make('AnotherClass')
print "DID closed() - locals :", locals().keys()
# NOT EXPECTED
try: print AnotherClass
except NameError, ex: print "OUCH:", ex
closed()
输出:
WILL __main__ - locals : ['creator', '__builtins__', '__file__', '__package__', '__name__', '__doc__']
WILL make() - callers locals : ['creator', '__builtins__', '__file__', '__package__', '__name__', '__doc__']
DID make() - callers locals : ['creator', '__builtins__', 'SomeClass', '__file__', '__package__', '__name__', '__doc__']
DID __main__ - locals : ['creator', '__builtins__', 'SomeClass', '__file__', '__package__', '__name__', '__doc__']
SomeClass : <class 'creator.SomeClass'>
--------------------------------------------------------------------------------
WILL closed() - locals : ['ClosedClass']
WILL make() - callers locals : ['ClosedClass']
DID make() - callers locals : ['ClosedClass', 'AnotherClass']
DID closed() - locals : ['ClosedClass', 'AnotherClass']
OUCH: global name 'AnotherClass' is not defined
当然我不想要OUCH:..
。
在locals()
内查看closed
可以想象它应该可以工作但是正如黑客中提到的那样,Python编译器正在优化本地人并且缺少新动态的引入。
如果我取消注释exec ''
行,那么它就可以了。
我可以使用全局范围创建这些类,但我正在尝试保持名称空间的清洁。
我当然可以做AnotherClass = creator.make('AnotherClass')
但是我试图保持 DRY 。
有没有办法让它在没有exec ''
黑客的情况下工作?
或者是否将它们变为全球性?
答案 0 :(得分:2)
否即可。 仅访问本地变量的方式是locals()
或vars()
,在这两种情况下,文档都明确指出无法保证对dict
的修改返回会影响局部变量,因此:没有办法可靠地做到这一点。
如果你想修改本地静态,那么可能你可以修改与该功能相关的代码对象以提供更多的本地人,但它可能不可能或者它可以真的很难做到可靠,我认为没有理由这样做。