【问题标题】:How do I call super in a method decorator in Python 3? [duplicate]如何在 Python 3 的方法装饰器中调用 super? [复制]
【发布时间】:2014-11-13 07:37:27
【问题描述】:

???如何填写?

def ensure_finished(iterator):
    try:
        next(iterator)
    except StopIteration:
        return
    else:
        raise RuntimeError


def derived_generator(method):
    def new_method(self, *args, **kwargs):
        x = method(self, *args, **kwargs)
        y = getattr(super(???, self), method.__name__)\
            (*args, **kwargs)

        for a, b in zip(x, y):
            assert a is None and b is None
            yield

        ensure_finished(x)
        ensure_finished(y)

    return new_method

【问题讨论】:

  • @chepner:同时迭代基类和超类迭代器。
  • 我只是将其添加为您之前关于定义方法的类的问题的用例(刚刚注意到您发布了两者),而不是在这里单独询问。
  • 为什么你什么都没有?
  • 我认为@chepner 是对的。这个问题的实际部分“我如何填写???”与前面的问题“给定一个方法,我如何返回它所属的类”相同,因为该问题的答案这个问题中的???
  • @greschd 因为重点是同步协程。

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


【解决方案1】:

编辑:由于 cmets 中提到的原因,这不起作用。我将把它留在这里,以便下一个试图回答的人不会做同样的事情(直到真正的答案出现)。

你应该使用type(self)

示例我稍微简化了你的代码,但精髓应该还在里面

def derived_generator(method):
    def new_method(self, *args, **kwargs):
        x = method(self, *args, **kwargs)
        y = getattr(super(type(self), self), method.__name__)\
            (*args, **kwargs)

        for a, b in zip(y, x):
            yield a, b

    return new_method

class BaseClass(object):
    def iterator(self):
        return [1, 2, 3]

class ChildClass(BaseClass):
    @derived_generator
    def iterator(self):
        return [4, 5, 6]

a = ChildClass()
for x in a.iterator():
    print(x)

【讨论】:

  • 这仅在您永远不会从子类的实例中调用此方法时才有效。例如,假设您创建 GrandchildClass 并在其中添加 @derived_generator 覆盖。所以GrandchildClass.iterator 将超级到ChildClass.iterator,这将再次超级到ChildClass.iterator,依此类推,直到遇到递归错误。 (这实际上与 Blckknight 在 rioppi 上个月现已删除的答案中指出的问题相同。)
  • 啊,对……没想到这一点。我应该把我的回复作为一个坏例子吗?
  • 更新:我找到了一个基于stackoverflow.com/a/3464154/5426033的hacky解决方案,想法是在``` def isinvoker(func): """A decorator calls super methods.""" def 中调整 self.__class__ call_super(self, *args, **kwargs): base_class= type(self).__bases__[0] child_class= type(self) self.__class__ = base_class print(f"decorated locals: {locals()}") fun = base_class.__getattribute__(self, 'f') fun(*args, **kwargs) self.__class__ = child_class return call_super ``
猜你喜欢
  • 2012-02-09
  • 2015-04-21
  • 2016-03-17
  • 2015-12-06
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
  • 2011-03-23
  • 2023-02-08
相关资源
最近更新 更多