![](/img/trans.png)
[英]Using class attributes to modify a docstring with a decorator in Python
[英]python global decorator for class attributes
下面是一段抽象的代码,它简化了我遇到的问题。 在此示例中,我有一个具有登录和注销属性的程序。 登录名与版本无关,而注销则与版本有关。
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)
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]
那显然是行不通的。 这有可能吗?
看起来像是一个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]
现在:
>>> a = A()
>>> a.login
'logged in'
>>> a.logout
'logged out'
>>> a.version = '2.0'
>>> a.logout
'logged out 2.0'
如果您有很多这样的属性,则可以自动化一些:
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]))
现在:
>>> a = A()
>>> a.login_message
'hello logger'
>>> a.logout
'goodbye logger'
>>> a.version = '2.0'
>>> a.logout
'goodbye logger 2.0'
每次创建A
的新实例时,“自动解决方案1”都会重新定义属性。 该解决方案避免了这种情况,但是涉及更多。 它利用了一个类装饰器。
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'
现在:
>>> a = A()
>>> a.logout
'goodbye logger'
>>> a.version = '2.0'
>>> a.logout
'goodbye logger 2.0'
您说“ self.login
和self.logout
不应以不同的方式访问。下面的代码保留了self.logout
字典,但将其重命名为self.logouts
以便我们可以将其作为属性来访问。类似的注释也适用于self.logout_message
。
此代码在Python 2或3上运行。
from __future__ import print_function
class Executor(object):
def do(self, s):
print('Executing %r' % s)
class A(object):
def __init__(self, version="1.0"):
self.version = version
self.login = "logged in"
self.login_message = "hello logger"
self.logouts = {
"1.0": "logged out",
"2.0": "logged out 2.0",
}
self.logout_messages = {
"1.0": "goodbye logger",
"2.0": "goodbye logger 2.0",
}
@property
def logout(self):
return self.logouts[self.version]
@property
def logout_message(self):
return self.logout_messages[self.version]
def perform(self, executor):
executor.do(self.login)
executor.do(self.logout)
executor = Executor()
executor.do('Tests')
#Test
a = A()
a.perform(executor)
print('msg', a.logout)
a.version = "2.0"
a.perform(executor)
print('msg', a.logout)
print()
b = A("2.0")
b.perform(executor)
print('msg', b.logout)
b.version = "3.0"
b.perform(executor)
产量
Executing 'Tests'
Executing 'logged in'
Executing 'logged out'
msg logged out
Executing 'logged in'
Executing 'logged out 2.0'
msg logged out 2.0
Executing 'logged in'
Executing 'logged out 2.0'
msg logged out 2.0
Executing 'logged in'
Traceback (most recent call last):
File "./qtest.py", line 69, in <module>
b.perform(executor)
File "./qtest.py", line 50, in perform
executor.do(self.logout)
File "./qtest.py", line 42, in logout
return self.logouts[self.version]
KeyError: '3.0'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.