如何在当前模块上调用setattr()?


140

如何将第一个参数“ object”传递给函数setattr(object, name, value),以在当前模块上设置变量?

例如:

setattr(object, "SOME_CONSTANT", 42);

具有与以下相同的效果:

SOME_CONSTANT = 42

在包含这些行的模块中(带有正确的object)。

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

Answers:


220
import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

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

globals()[name] = value

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

vars()[name] = value

这更加简洁,但是在函数内部不起作用(vars()给出在其范围内调用的变量:在全局范围内调用时模块的变量,然后可以使用R / W,但在函数中可以使用变量在函数中调用时,然后必须将其视为R / O - Python在线文档对此特定区别可能会造成混淆。


9
该文档给出了有关修改vars()的警告。docs.python.org/library/functions.html#vars。什么时候可以这样做?
unutbu 2010年

2
@〜unutbu,我并不是真的会说“还可以”,但是当您vars()在模块级作用域而不是在函数内部调用时,它将起作用。
Mike Graham 2010年

4
vars()globals()在模块范围内等效(因此返回一个真实的,可修改的字典),但locals()在函数范围内等效(因此返回一个永不被修改的伪字典)。我vars()在模块作用域中使用它,因为它节省了3个字符(一个音节),而不是它的同义词globals();-)
Alex Martelli 2010年

14
是的,它会破坏Python编译器所做的最重要的单个优化:函数的局部变量保存在字典中,它们存放在紧密的值向量中,每个局部变量访问都使用该向量中的索引,而不是名称查询。为了击败优化,强迫您想要存在的字典,以以下方式启动函数exec '':给函数计时,并以各种方式循环几个循环,您将看到此核心优化对Python性能的重要性。
亚历克斯·马丁里

3
@msw,我认为您忘记了“实用胜过纯度” ;-)。
亚历克斯·马丁里

6

如果必须从模块内部设置模块范围的变量,那有什么问题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']

1
是的,我一直(其中“总是”被定义为“我最近学习Python的最近几个月”)发现global but not really声明令人费解。我想可能是模块名称空间之前的历史遗物。
msw 2010年

1
最初的问题是询问如何设置名称由字符串指定的属性(与我目前正在搜索的名称相同),因此这无济于事。
Curt's


-1
  1. 你不会的 你会做globals()["SOME_CONSTANT"] = 42
  2. 你不会的 您会将动态生成的内容存储在模块以外的其他位置。

是的,SOME_CONSTANT在运行时计算的不是完全恒定的。如果globals()您不可用,则必须进入另一个模块来修改其属性。一定会让人们感到疑惑。
MSW 2010年

3
常数和可变是互斥的。不是常量和动态生成的。我生成的值始终是相同的,并且是根据其他“常量”确定的,以节省我的运算和输入。
马特·乔纳
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.