【问题标题】:Adding dynamic class to callers namespace向调用者命名空间添加动态类
【发布时间】:2013-03-06 19:46:38
【问题描述】:

问题

无法在函数内动态创建具有本地范围的类,但可以在顶层工作。

问题

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


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

以便我能够执行以下操作。

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:..

closed 中查看locals() 可以想象它应该可以工作,但正如黑客中提到的那样,Python 编译器正在优化本地变量并且错过了新动态编译器的引入。

如果我取消注释 exec '' 行,那么它可以工作。

我可以创建具有全局范围的这些类,但我试图保持我的命名空间干净。

我当然可以使用AnotherClass = creator.make('AnotherClass'),但我正在努力保持它DRY

有没有办法让它在没有exec '' hack 的情况下工作?

还是让它们全球化?

【问题讨论】:

    标签: python


    【解决方案1】:

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

    如果你想修改局部变量静态然后也许你可以修改与函数关联的代码对象以提供更多局部变量,但这可能是不可能的,或者它可以确实很难可靠地做到这一点,我认为没有理由这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-24
      • 2011-07-23
      • 1970-01-01
      • 2019-11-13
      • 2011-08-22
      • 2015-05-24
      • 2014-02-07
      • 2016-05-05
      相关资源
      最近更新 更多