将对象属性导入为全局变量

时间:2012-02-13 11:08:02

标签: python

我有一个小的python脚本,用作配置文件。结构就像

project=Project(param1=..., param2=..., ...)
project.add_plugins(P1(data=project.db1()),
                    P2(data=project.db2()))
project.run_plugins(get_selected())

为了便于记法,我想介绍类似

的内容
db1=project.db1
db2=project.db2

表示项目的所有属性,因此我不需要写出project.。你能为自动为所有属性建议一个很好的方法吗?

2 个答案:

答案 0 :(得分:1)

我认为这不是一个好主意(请参阅我对您的问题的评论),但您可以使用内置的globals执行此操作:

for attr in dir(project):
    if not attr.startswith("_"):
        globals()[attr] = getattr(project, attr)

我不认为这是一个好主意的原因是它污染全局命名空间的东西是以一个非常整齐地包装在逻辑命名的命名空间中开始的。你的情况会越来越糟。

Python的禅宗(import this)最后一行写着:

Namespaces are one honking great idea -- let's do more of those!

答案 1 :(得分:1)

没有什么能阻止你写作:

db1=project.db1
db2=project.db2

从您的示例看,db1和db2是方法。如果是,您可以执行作业并根据需要致电db1()db2()

如果它们是可变属性,您可以安全地改变它们,但要注意重新绑定短名称不会以任何方式影响原始属性(就像重新绑定从导入创建的名称不会影响原始属性一样)。 / p>

Python的标准库在一些地方使用这个技巧。例如,查看公开random.py类的Random,但也创建它的实例并通过普通名称导出该实例的方法:

# Create one instance, seeded from current time, and export its methods
# as module-level functions.  The functions share state across all uses
#(both in the user's code and in the Python libraries), but that's fine
# for most programs and is easier for the casual user than making them
# instantiate their own Random() instance.

_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
triangular = _inst.triangular
...

要自动执行此操作,我将使用装饰器来构建导出名称的__all__列表(导入模块的任何人都需要这些名称),然后在实例化类之后单独创建名称。 / p>

__all__ = []
def exported(f):
    __all__.append(f.__name__)
    return f
class Project:
    @exported
    def db1(self): ...
project = Project()

for name in __all__:
    if hasattr(project, name):
        globals()[name] = getattr(project, name)