【问题标题】:Calling different parent-class methods with one decorator用一个装饰器调用不同的父类方法
【发布时间】:2019-04-21 06:09:18
【问题描述】:

所以基本上我的问题是这样的。

class A():
    def func(self):
        return 3

class B():
    def func(self):
        return 4

class AA(A):
    def func(self):
        return super(AA, self).func

class BB(B):
    def func(self):
        return super(BB, self).func

func 函数正在做一些工作,其中一件事是从它的父类获取一些属性(或运行方法或其他)。

由于func 最初在两种情况下都执行相同的逻辑(除了只有父类更改),我想用装饰器来做这件事。

有可能吗?如果是的话怎么办?我是否必须以某种方式将父类作为参数传递?

我将非常感谢困扰我一段时间的答案。

【问题讨论】:

  • 您的问题中定义了四种不同的func() 方法,因此当您引用它时,您需要具体说明。说“既然 func 最初是……”之类的话是没有意义的。

标签: python inheritance decorator python-decorators


【解决方案1】:

不需要使用super来访问父类的数据属性。

类也不需要父类才能访问数据属性。

您可以使用 mixin 来完成这项工作:

# A and B stay the same - they still have a c attribute
class A():
    c = 3

class B():
    c = 4  # I've changed B to make it clear below

#Instead have a mixin which defines func()
class Mixin:
    def func(self):
        # func has its behaviour here
        return self.c

class AA(Mixin, A):
    pass
class BB(Mixin, B):
    pass

a = AA()
b = BB()
print(a.func())
print(b.func())

输出:

3
4

【讨论】:

  • 问题是当基类方法名称与父类中的名称相同时。这就是我的情况。我将编辑问题以使其更清楚。
  • 在 python3 中你可以只使用 super().func()
  • 您愿意这样并在我们正在讨论的示例中展示如何做到这一点吗?我尝试做装饰器,但在其中调用 super().func() 给出:class cell not found runtime error.
【解决方案2】:

您可以通过在其中定义一个通用方法来执行您想要的操作,然后将其添加到被装饰的类中,从而使用单个类装饰器来实现。这就是我的意思:

def my_decorator(cls):
    def call_super_func(self):
        return super(type(self), self).func()

    setattr(cls, 'call_super_func', call_super_func)
    return cls

class A():
    def func(self):
        print('in A.func')
        return 3

class B():
    def func(self):
        print('in B.func')
        return 4

@my_decorator
class AA(A):
    def func(self):
        print('in AA.func')
        return self.call_super_func()

@my_decorator
class BB(B):
    def func(self):
        print('in BB.func')
        return self.call_super_func()


aa = AA()
aa.func()
bb = BB()
bb.func()

输出:

in AA.func
in A.func
in BB.func
in B.func

当然,您可以消除这样做的需要,只需为 AB 定义基类,其中包含 call_super_func() 方法,然后它们都会继承。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 2014-01-14
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2015-12-08
    相关资源
    最近更新 更多