Der*_*ist 2 python properties decorator python-3.x
下面是一段抽象的代码,它简化了我遇到的问题。在此示例中,我有一个具有登录和注销属性的程序。登录与版本无关,注销与版本相关。
class A(class):
def __init__(self):
self.version = "1.0"
self.login = "logged in"
self.login_message = "hello logger"
self.logout = {"1.0": "logged out",
"2.0": "logged out 2.0"}
self.logout_message = {"1.0": "goodbye logger",
"2.0": "goodbye logger 2.0"}
def perform(self, executor):
executor.do(self.login)
executor.do(self.logout)
Run Code Online (Sandbox Code Playgroud)
executor
是一个执行实际操作的外部接口,它应该接收一个字符串。该do
功能无法更改。版本可以并且会在运行时改变,所以我正在寻找某种全局装饰器/属性,当访问装饰属性时,它会调用一个函数。目标是在每个版本发送到executor.do
.
答案显然是改变perform
功能executer.do(self.logout[self.version])
,但self.login
并self.logout
不宜不同的方式访问。有些继承self.logout
只是一个字符串,并且perform
是共享的。
我在想这样的事情:
self.version = "1.0"
self.login = "logged in"
self.login_message = "hello logger"
@by_version
self.logout = {"1.0": "logged out",
"2.0": "logged out 2.0"}
@by_version
self.logout_message = {"1.0": "goodbye logger",
"2.0": "goodbye logger 2.0"}
def by_version(self, attribute):
return attribute[self.version]
Run Code Online (Sandbox Code Playgroud)
那显然行不通。这甚至可能吗?
看起来像property
装饰器的用例:
class A(object):
def __init__(self):
self.version = "1.0"
self.login = "logged in"
self.login_message = "hello logger"
@property
def logout(self):
return {"1.0": "logged out", "2.0": "logged out 2.0"}[self.version]
@property
def logout_message(self):
return {"1.0": "goodbye logger", "2.0": "goodbye logger 2.0"}[self.version]
Run Code Online (Sandbox Code Playgroud)
现在:
>>> a = A()
>>> a.login
'logged in'
>>> a.logout
'logged out'
>>> a.version = '2.0'
>>> a.logout
'logged out 2.0'
Run Code Online (Sandbox Code Playgroud)
如果你有很多这样的属性,你可以自动化一点:
class A(object):
def __init__(self):
self.version = '1.0'
self.login = 'logged in'
self.login_message = 'hello logger'
property_attrs = {'logout': {'1.0': 'logged out',
'2.0': 'logged out 2.0'},
'logout_message': {'1.0': 'goodbye logger',
'2.0': 'goodbye logger 2.0'}}
for name, value in property_attrs.items():
setattr(self.__class__, name, property(lambda x: value[x.version]))
Run Code Online (Sandbox Code Playgroud)
现在:
>>> a = A()
>>> a.login_message
'hello logger'
>>> a.logout
'goodbye logger'
>>> a.version = '2.0'
>>> a.logout
'goodbye logger 2.0'
Run Code Online (Sandbox Code Playgroud)
每次创建新实例时,“自动化解决方案 1”都会重新定义属性A
。此解决方案避免了这种情况,但涉及更多。它使用类装饰器。
property_attrs = {'logout': {'1.0': 'logged out', '2.0': 'logged out 2.0'},
'logout_message': {'1.0': 'goodbye logger', '2.0': 'goodbye logger 2.0'}}
def add_properties(property_attrs):
def decorate(cls):
for name, value in property_attrs.items():
setattr(cls, name, property(lambda self: value[self.version]))
return cls
return decorate
@add_properties(property_attrs)
class A(object):
def __init__(self):
self.version = '1.0'
self.login = 'logged in'
self.login_message = 'hello logger'
Run Code Online (Sandbox Code Playgroud)
现在:
>>> a = A()
>>> a.logout
'goodbye logger'
>>> a.version = '2.0'
>>> a.logout
'goodbye logger 2.0'
Run Code Online (Sandbox Code Playgroud)