是否有任何方法使locals()和globals()与defaultdict类似

时间:2016-02-16 15:37:21

标签: python variables python-internals locals

是否可以在运行时更改Python中localdict变量的行为?

在Python中,locals()提供对当前执行范围中的变量的引用,该变量是>>> locals() {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None} 对象。

locals()

是否可以将locals()返回的引用替换为defaultdict,但在替换之前保留以前的值(UnboundLocalException的副本)?

我希望在使用未初始化的变量并访问执行范围中的任何变量名时避免locals()异常(未初始化的变量将采用指定的默认值)。

我试图修改java -cp zookeeper.jar:lib/log4j-1.2.15.jar:conf \ org.apache.zookeeper.server.quorum.QuorumPeerMain zoo.cfg返回的值,将其重新分配给当地人,但没有成功。

同样的问题适用于globals()

2 个答案:

答案 0 :(得分:4)

不,你不能。 locals()只是用于函数的实际命名空间的反射

出于性能原因,实际的命名空间是数组,并且不会按名称而是按索引查找本地。事后,您无法为此添加新名称,因为编译器根本没有考虑数组中的更多引用。

请注意,对于缺少全局而不是本地人,会抛出NameError个异常。本地名称,如果尚未绑定,则抛出UnboundLocalException。但是,您无法使用defaultdict替换globals()字典;模块对象的__dict__属性是只读的。即使它不是只读的,也只支持内置的dict类型,因为在命名空间中查找名称的方式;这是by design

答案 1 :(得分:2)

是的,使用metaclasses Python工具来修改class语句的行为。

此处,DefaultDictMetadefaultdict方法返回__prepare__的实例。因此,具有DefaultDictMeta元类的任何类将最终使用defaultdict的实例作为其命名空间。这意味着NoNameErrorsInBody正文中的名称查找无法

from collections import defaultdict

class DefaultDictMeta(type):
    def __prepare__(name, bases, default=None, **kwargs):
        return defaultdict(lambda: default)

    def __new__(meta, name, bases, dct, **kwargs):
        # swallow keyword arguments
        return super().__new__(meta, name, bases, dct)

    def __init__(cls, name, bases, dct, **kwargs):
        # swallow keyword arguments
        pass

class NoNameErrorsInBody(metaclass=DefaultDictMeta, default=2):
    x = y + 3  # y is not defined


>>> NoNameErrorsInBody.x
5

不言而喻,在现实世界的代码中你永远不应该这样做。我只是为了一点乐趣而展示它。 (想象一下,尝试调试在使用无效名称时不会告诉您的代码。它很糟糕,比如,我不知道,Javascript还是什么。)