tl; dr:属性装饰器如何与类级别的函数定义一起使用,但不能与模块级别的定义一起使用?为什么属性Decorator只能定义类?
我正在将属性装饰器应用到某些模块级别的函数中,认为它们将允许我通过属性查找来调用方法。
这是特别诱人的,因为我是定义一组配置功能,如get_port
,get_hostname
,等等,所有这些都可能被替换的更简单,更简洁的财产同行:port
,hostname
等
因此,config.get_port()
只会是好得多config.port
我很惊讶,当我发现下面的回溯,证明这不是一个可行的选择:
TypeError: int() argument must be a string or a number, not 'property'
我知道我已经在模块级看到过类似于属性的功能,因为我曾经使用优雅但很好用的pbs library来将它用于脚本shell命令。
下面有趣的黑客可以在pbs library source code找到。它可以在模块级别上进行类似属性的属性查找,但这是可怕的,可怕的黑客行为。
# this is a thin wrapper around THIS module (we patch sys.modules[__name__]).
# this is in the case that the user does a "from pbs import whatever"
# in other words, they only want to import certain programs, not the whole
# system PATH worth of commands. in this case, we just proxy the
# import lookup to our Environment class
class SelfWrapper(ModuleType):
def __init__(self, self_module):
# this is super ugly to have to copy attributes like this,
# but it seems to be the only way to make reload() behave
# nicely. if i make these attributes dynamic lookups in
# __getattr__, reload sometimes chokes in weird ways...
for attr in ["__builtins__", "__doc__", "__name__", "__package__"]:
setattr(self, attr, getattr(self_module, attr))
self.self_module = self_module
self.env = Environment(globals())
def __getattr__(self, name):
return self.env[name]
下面是将此类插入到导入名称空间的代码。它实际上直接修补sys.modules
!
# we're being run as a stand-alone script, fire up a REPL
if __name__ == "__main__":
globs = globals()
f_globals = {}
for k in ["__builtins__", "__doc__", "__name__", "__package__"]:
f_globals[k] = globs[k]
env = Environment(f_globals)
run_repl(env)
# we're being imported from somewhere
else:
self = sys.modules[__name__]
sys.modules[__name__] = SelfWrapper(self)
现在,我所看到的长度pbs
要经过,我在想为什么Python中的这一设施不是直接内置于语言。特别是property
装饰者似乎是添加这种功能的自然地方。
是否有任何partiuclar原因或动机为什么这不是直接建立?
为了更容易找到:现在有一个名为mprop的模块,它可以为你做到这一点https://pypi.python.org/pypi/mprop – AbdealiJK 2017-04-16 05:28:35