【问题标题】:Override the value of a static variable while using decorator使用装饰器时覆盖静态变量的值
【发布时间】:2015-11-13 03:15:11
【问题描述】:

我创建了一个如下所示的类:

class Simon:

    name = 'Simon'

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

如果我想让Simon坐下,我可以这样做:

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

要将 Simon 替换为另一个名字,比如 Eva,我可以这样子类化它:

class Eva(Simon):

    name = 'Eva'

结果:

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

现在我想通过创建一个名为 to_past_tense 的装饰器将 says 更改为 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'

如何覆盖该值?

如果标题不够准确和清晰,请帮我改进,谢谢!

【问题讨论】:

  • 查看硬编码的类名:return cls.to_past_tense(cls, Simon.says)(*arg, **kw)
  • 我已经尝试了@Daniel Roseman 的建议,但没有任何意义。

标签: python python-3.x inheritance decorator python-decorators


【解决方案1】:

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

如果您想获取被覆盖的类方法但要绑定到当前类,请使用super() proxy object

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

super()对象会搜索类的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'

【讨论】:

  • @OwenL:您定义此方法的当前类应该是,是的,因为 super() 然后使用它在 MRO 中查找下一个类。在 Python 3 中,你可以使用super().says,所以没有参数。
  • @OwenL:啊,你将其标记为 Python 3。将更新。
  • 完美!非常感谢!
【解决方案2】:

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

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

【讨论】:

  • 但我得到了这个:RuntimeError: maximum recursion depth exceeded
  • 那是因为cls.say 指向Eva.say,所以是的,这会导致方法调用自身。
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 2010-10-10
  • 2014-07-22
  • 2017-06-19
  • 1970-01-01
  • 2013-10-27
相关资源
最近更新 更多