![](/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.