将动态类添加到调用者名称空间

时间:2013-03-06 19:46:38

标签: python

问题

  

无法在函数中动态创建具有局部作用域的类,但在顶层工作。

问题

  

如何在正确的命名空间范围内动态创建类。


我正在尝试动态创建添加到调用者名称空间的类。

这样我就可以做到以下几点。

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 ''黑客的情况下工作?

或者是否将它们变为全球性?

1 个答案:

答案 0 :(得分:2)

即可。 访问本地变量的方式是locals()vars(),在这两种情况下,文档都明确指出无法保证对dict的修改返回会影响局部变量,因此:没有办法可靠地做到这一点。

如果你想修改本地静态,那么可能你可以修改与该功能相关的代码对象以提供更多的本地人,但它可能不可能或者它可以真的很难做到可靠,我认为没有理由这样做。