如何在运行时向模块添加属性?

26

我需要在运行时添加模块属性。例如,当加载模块时,它会读取包含数据的文件。我希望该数据作为模块属性可用,但该数据仅在运行时可用。

如何在运行时添加模块属性?

7个回答

43

感谢@Dharmesh。这正是我所需要的。只需进行一处更改。由于该模块不会导入自身,因此可以执行以下操作来获取模块对象:

setattr(sys.modules[__name__], 'attr1', 'attr1')


18

如果你直到运行时才知道属性的名称,请使用 setattr

>>> import mymodule
>>> setattr(mymodule, 'point', (1.0, 4.0))
>>> mymodule.point
(1.0, 4.0)

1
这绝不是一个好的例子!模块应该设置自己的属性,而不是调用者!! - John Machin
2
@John Machin:在这种情况下,@Jeremy可以像Werkzeug代码一样进行一些模块魔法:https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/__init__.py - Jeff Bauer
Werkzeug 的更新链接:https://github.com/pallets/werkzeug - Jeff Bauer

5

模块属性是模块全局范围内的变量。

如果您想要在“运行时”从模块本身设置属性,则正确的方法是

globals()['name'] = value

(注:这种方法仅适用于全局,而不适用于局部变量。)
如果您想从导入模块的作用域设置属性,请直接设置它:
import myModule
setattr(myModule, 'name', 10)

完整的示例:

#m.py
def setGlobal(name, value):
    globals()[name] = value

--

#main.py
import m

m.setGlobal('foo', 10)
print(m.foo) #--> 10

#Moreover:

from m import foo
print(foo) #--> 10   (as Expected)

m.setGlobal('foo', 20)
print(m.foo) #--> 20  (also as expected)

#But:
print(foo) #--> 10

4
创建动态类'Module',并使用类似于字典的方式动态添加属性:
attributes = {'attr1': 'attr1', 'attr2': 'attr2'}
module = type('Module', (), attributes)

或者只创建动态类'Module'

module = type('Module', (), {})

并使用setattr方法添加属性,如下所示:

setattr(module, 'attr3', 'attr3')

或者

import module
setattr(module, 'attr1', 'attr1')

1

只需设置它。

my_object = MyObject()
my_object.my_custom_attribute = 'my_value'

如果你知道“my_custom_attribute”,那么它能很好地运作,但在运行时我却不知道它是什么。 - jlconlin
你不知道值或键是什么?如果是值,你可以在运行时像其他任何方法一样进行操作。如果是键,只需使用 setattr(my_object, my_key, 'my_value') 即可。 - Daniel Roseman
@Jeremy,@martineau:“根据上下文知道期望的内容”对我来说似乎有些可疑。每个调用者似乎需要大量的if/elif*/else代码。 - John Machin
@Jeremy:在这种情况下,您需要像@Jeff Bauer在他的答案中建议的那样执行setattr()(并且@Daniel Roseman在他的评论中提到)。可能的替代方法是提供一个预定义的模块方法,该方法接受属性名称作为参数并返回其值(或类似的内容)。 - martineau
@John Machin:不一定...也许需要一些try/except块(这些块本来就应该在那里)。 - martineau
显示剩余2条评论

0
将其作为键添加到对象的内部字典__dict__中。
my_object.__dict__['newattribute'] = 'attributevalue'

-7
模块的全局作用域是模块本身,因此只需设置一个全局变量即可。
# module.py
a = 1

# script.py
import module
print module.a
# 1

2
-1:这个问题是关于在运行时添加属性的。这个回答并没有解决该问题。 - Jaap Versteegh
2
不要无礼。请解释运行时位在哪里。就像:module.py被导入后没有"a",然后在module.py的字典中添加了"a",即“在运行时期间”。这就是我对这个问题中“运行时”理解的方式。如果您认为我误解了,请随意解释。 - Jaap Versteegh
1
感谢您向我解释Python的工作原理,但是原始问题明确说明作者在编写模块时不知道属性的名称,因此您的回答并没有回答问题。你可以尽情地讨论运行时的含义等等,但是归根结底,你必须承认你没有回答问题,我的反对票是正确的。你可以“祝贺”我,并说我“自豪地宣布”一些事情,这只是为了避免面对你在这里是错误的事实而已! - Jaap Versteegh
但是对于任何其他人而言:这个问题与属性的名称无关,而是关于数据(例如值)在运行时不可用的问题。 - Glenn Maynard
1
尽管那可能更微不足道,但是你的例子同样没有展示在编写该模块的时候该数据是未知的情况下设置属性的数据。 (顺便说一句,这次谈话中所有与主题无关/丑陋的东西都是你的) - Jaap Versteegh
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接