使用装饰器时覆盖静态变量的值

Override the value of a static variable while using decorator

我创建了一个 class 如下所示:

class Simon:

    name = 'Simon'

    @classmethod
    def says(cls, sentence):
        return '%s says: %s' % (cls.name, sentence)

如果我想西蒙坐下,我可以这样做:

>>> Simon.says('sit down')
'Simon says: sit down'

要用另一个名字替换 Simon,比如 Eva,我可以这样子 class:

class Eva(Simon):

    name = 'Eva'

结果:

>>> Eva.says('stand up')
'Eva says: stand up'

现在我想通过创建一个名为 to_past_tense:

的装饰器将 said 更改为 said
class Eva(Simon):

    name = 'Eva'

    def to_past_tense(self, func):
        def wrapper(*arg, **kw):
            present_tense = func(*arg, **kw)
            past_tense = present_tense.replace('says', 'said')
            return past_tense
        return wrapper

    @classmethod
    def says(cls, *arg, **kw):
        return cls.to_past_tense(cls, Simon.says)(*arg, **kw)

如果我这样做:

>>> Eva.says('stand up')

我期待的是:

'Eva said: stand up'

但事实上我得到了这个

'Simon said: stand up'

如何覆盖该值?

还有,如果标题不准确和不清晰,请帮我改进一下,谢谢!

我不完全确定你想在这里实现什么,但我想你需要将 cls.says 传递给方法:

return cls.to_past_tense(cls, cls.says)(*arg, **kw)

您正在使用 Simon.says,检索绑定 class。

如果您想获取覆盖的 class 方法但将其绑定到当前 class,请使用 super() proxy object:

@classmethod
def says(cls, *arg, **kw):
    return cls.to_past_tense(cls, super().says)(*arg, **kw)

super()对象会搜索class的MRO,找到Simon上的says方法,然后绑定到cls对象上对你来说,所以 cls.name 值仍然是从 Eva:

中查找的
>>> class Simon:
...     name = 'Simon'
...     @classmethod
...     def says(cls, sentence):
...         return '%s says: %s' % (cls.name, sentence)
... 
>>> class Eva(Simon):
...     name = 'Eva'
...     def to_past_tense(self, func):
...         def wrapper(*arg, **kw):
...             present_tense = func(*arg, **kw)
...             past_tense = present_tense.replace('says', 'said')
...             return past_tense
...         return wrapper
...     @classmethod
...     def says(cls, *arg, **kw):
...         return cls.to_past_tense(cls, super().says)(*arg, **kw)
... 
>>> Eva.says('Hello')
'Eva said: Hello'