用于类属性的python全局装饰器

Derorrist

下面是一段抽象的代码,它简化了我遇到的问题。在此示例中,我有一个具有登录和注销属性的程序。登录名与版本无关,而注销则与版本有关。

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.loginself.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'     

自动化解决方案1

如果您有很多这样的属性,则可以自动化一些:

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'

自动化解决方案2

每次创建的新实例时,“自动化解决方案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'

现在:

>>> a = A()
>>> a.logout
'goodbye logger'
>>> a.version = '2.0'
>>> a.logout
'goodbye logger 2.0'

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章