我有一个Python模块,它有几个带有硬编码值的变量,这些变量在整个项目中使用。我想以某种方式将变量绑定到函数以重定向到配置文件。这可能吗?
(?:\\<[^<>!]*?\\>\\n?)((.|\\n)*?)(?:\\<!.*\\>(\\n|$)?)
我想要做的只是更改# hardcoded_values.py
foo = 'abc'
bar = 1234
# usage somewhere else in another module
from hardcoded_values import *
print foo
print bar
,以便hardcoded_values.py
透明地调用函数。
print foo
# hardcoded_values.py
import config
foo = SomeWrapper(config.get_value, 'foo') # or whatever you can think of to call config.get_value('foo')
...
是使用变量config.get_value
时使用参数'foo'
调用的函数(如foo
中所示)。
答案 0 :(得分:2)
如果模块的客户端代码使用from hardcoded_variables import *
,则无法执行此操作。这引用了另一个模块命名空间中hardcoded_variables
的内容,之后你就无法对它们做任何事情。
如果可以将客户端代码更改为仅导入模块(例如import hardcoded_variables
)然后访问其属性(使用hardcoded_variables.foo
),则确实有机会,但这有点尴尬。< / p>
Python缓存已在sys.modules
(字典)中导入的模块。您可以将该字典中的模块替换为其他对象(例如自定义类的实例),并在访问对象的属性时使用property
对象或其他描述符来实现特殊行为。
尝试让您的新hardcoded_variables.py
看起来像这样(并考虑重命名它!):
import sys
class DummyModule(object):
def __init__(self):
self._bar = 1233
@property
def foo(self):
print("foo called!")
return "abc"
@property
def bar(self):
self._bar += 1
return self._bar
if __name__ != "__main__": # Note, this is the opposite of the usual boilerplate
sys.modules[__name__] = DummyModule()
答案 1 :(得分:2)
如果您导入from hardcoded_values import *
,我很确定您无法执行您想要执行的操作。
你想要做的是将foo
设置为某个函数,然后应用property
装饰器(或等效的),这样你就可以调用foo作为foo
而不是{{ 1}}。您无法将属性装饰器应用于模块,原因如下:Why Is The property Decorator Only Defined For Classes?
现在,如果你去foo()
那么我觉得有办法做你想要的import hardcoded_values
。我有一种非常好的感觉,我将要描述的是一个永远不应该使用的 BAD IDEA ,但我认为它很有趣。
BAD IDEA ???
所以说你想用我的系统hardcoded_values.foo
替换os.EX_USAGE
之类的常量,然后将其称为64
而不是os.EX_USAGE
。我们需要能够使用os.EX_USAGE()
装饰器,但为此我们需要property
以外的类型。
所以可以做的是动态创建一个新类型并转储到模块的module
中,该模块带有一个以模块为参数的类型工厂函数:
__dict__
现在我将导入os:
def module_class_factory(module):
ModuleClass = type('ModuleClass' + module.__name__,
(object,), module.__dict__)
return ModuleClass
现在我将创建一个类>>> import os
>>> os.EX_USAGE
64
>>> os.getcwd()
'/Users/Eric'
,并将名称OsClass
绑定到此类的实例:
os
一切似乎仍然有效。现在定义一个替换>>> OsClass = module_class_factory(os)
>>> os = OsClass()
>>> os.EX_USAGE
64
>>> os.getcwd()
'/Users/Eric'
的函数,注意它需要一个伪os.EX_USAGE
参数:
self
...并将类属性>>> def foo(self):
... return 42
...
绑定到函数:
OsClass.EX_USAGE
>>> OsClass.EX_USAGE = foo
>>> os.EX_USAGE()
42
对象调用它时有效!现在只需应用属性装饰器:
os
现在,模块中定义的常量已被函数调用透明地替换。
答案 2 :(得分:0)
如果我理解正确,您希望每次尝试访问变量时都会评估hardcoded_variables
模块。
我可能在文档中有hardcoded_variables
(例如json?)和自定义包装函数,如:
import json
def getSettings(var):
with open('path/to/variables.json') as infl:
data = json.load(infl)
return infl[var]