【问题标题】:How do I call setattr() on the current module?如何在当前模块上调用 setattr()?
【发布时间】:2011-02-25 09:11:45
【问题描述】:

我应该将什么作为第一个参数“object”传递给函数setattr(object, name, value),以在当前模块上设置变量?

例如:

setattr(object, "SOME_CONSTANT", 42);

产生与以下相同的效果:

SOME_CONSTANT = 42

在包含这些行的模块内(使用正确的object)。

我在模块级别动态生成多个值,由于我无法在模块级别定义__getattr__,这是我的后备方案。

【问题讨论】:

    标签: python module global-variables getattr setattr


    【解决方案1】:
    import sys
    
    thismodule = sys.modules[__name__]
    
    setattr(thismodule, name, value)
    

    或者,不使用setattr(它破坏了问题的字母,但满足相同的实际目的;-):

    globals()[name] = value
    

    注意:在模块范围内,后者等价于:

    vars()[name] = value
    

    这更简洁一点,但不能在函数内工作(vars() 给出了它被调用的范围的变量:在全局范围内调用模块的变量,然后可以使用它 R /W,但是在函数中调用函数的变量,然后它必须被视为 R/O——Python 在线文档可能会有点混淆这个特定的区别。

    【讨论】:

    • 文档给出了关于修改 vars() 的警告。 docs.python.org/library/functions.html#vars 。什么时候可以这样做?
    • @~unutbu,我不会真的说它“很好”,但是当您在模块级范围而不是函数内部调用 vars() 时,它会起作用。
    • vars() 在模块范围内等效于 globals()(因此返回一个真实的、可修改的 dict),但在函数范围内等效于 locals()(因此返回一个永不修改伪字典)。我在模块范围内使用vars(),因为它保存了3个字符,一个音节,而不是它的同义词在那个范围内globals();-)
    • 是的,它会破坏 Python 编译器所做的最重要的优化:函数的局部变量保存在字典中,它们位于值,并且每个局部变量访问都使用该向量中的索引,而不是名称查找。为了打败优化,强制你想要存在的dict,用exec ''开始函数:对函数计时,每次循环都有几个实质性的循环,你会看到这个核心优化对Python性能的重要性。
    • @msw,我想你忘记了“实用胜过纯洁”;-)。
    【解决方案2】:
    1. 你不会的。你会做globals()["SOME_CONSTANT"] = 42
    2. 你不会的。您可以将动态生成的内容存储在模块以外的某个地方。

    【讨论】:

    • 是的,SOME_CONSTANT 在运行时计算并不完全恒定。如果globals() 对您不可用,那么您必须进入另一个模块来修改其属性;这一定会让人们产生疑惑。
    • 常量和可变是互斥的。常量和动态生成的不是。我生成的值总是相同的,并且基于进一步的“常量”来确定,以节省我的算术和打字。
    【解决方案3】:

    如果必须在模块内设置模块范围的变量,global 有什么问题?

    # my_module.py
    
    def define_module_scoped_variables():
        global a, b, c
        a, b, c = 'a', ['b'], 3
    

    因此:

    >>> import my_module
    >>> my_module.define_module_scoped_variables()
    >>> a
    NameError: name 'a' is not defined
    >>> my_module.a
    'a'
    >>> my_module.b
    ['b']
    

    【讨论】:

    • 是的,我一直(其中“一直”被定义为“最近几个月我一直在学习 Python”)发现 global but not really 声明令人费解。我想它可能是模块命名空间之前的历史遗迹。
    • 最初的问题是询问如何设置一个名称由字符串给出的属性(我目前正在搜索相同的东西),所以这无济于事。
    【解决方案4】:

    在 Python 3.7 中,您将能够在模块级别 (related answer) 使用 __getattr__

    PEP 562

    def __getattr__(name):
        if name == "SOME_CONSTANT":
            return 42
        raise AttributeError(f"module {__name__} has no attribute {name}")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多