为了账号安全,请及时绑定邮箱和手机立即绑定

使 __call__ 成为可用于所有派生类的基类中的特定接口

使 __call__ 成为可用于所有派生类的基类中的特定接口

慕盖茨4494581 2021-09-14 17:47:03
我有一个带有公共的基类fn。我想让层次系统中的所有类都可以调用,并且它们__call__ 实际上将它们的工作转换为fn,语义类似于Class.__call__ = fn. 以下代码显示了我目前的实现方式。class Base:    def fn(self, *input):        # ...    __call__ = fnclass Derived(Base):    def fn(self, input):        # ...    __call__ = fn我知道有一种设计只__call__在 Base 类和 in__call__的函数体中定义 a ,以将其工作转换为fn每个派生类实现自己的fn. 语义就像“继承一个公共接口并从Base实现,并且在这个公共接口中,每个Derived类定义了自己的实现版本”。但是,其中一些fn具有不同的参数列表,并不总是与 Base 相同,就像我上面展示的情况一样。上面的代码可以工作,但我想肯定有更好的解决方案,没有在层次系统的所有类中重复定义。那么无论如何要__call__在 Base 类中指定唯一的一次,但使其可用于所有派生类?
查看完整描述

2 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

如果您使用的是 Python 版本 >= 3.6,您可以编写一个类的__init_subclass__方法Base,将__call__子类的属性分配为其fn属性:


class Base:

    def fn(self, *args):

        return args

    __call__ = fn

    def __init_subclass__(cls):

        cls.__call__ = cls.fn


class Derived(Base):

    def fn(self, arg):

        print("In derived")

        return arg



Base()(1, 2, 3)

# (1, 2, 3)


Derived()(1)

# In derived

# 1

如果您使用的是旧版本的 Python,您可以使用元类实现类似的效果。


class BaseMeta(type):

    def __init__(cls, *args, **kwargs):

        super().__init__(*args, **kwargs)

        cls.__call__ = cls.fn


class Base(metaclass=BaseMeta):

    def fn(self, *args):

        return args


class Derived(Base):

    def fn(self, arg):

        print("In derived")

        return arg


查看完整回答
反对 回复 2021-09-14
?
九州编程

TA贡献1785条经验 获得超4个赞

在您提供的示例中,无需使用__call__. 已经有一个非常好的机制,因为python会调用类构造函数。如此简单,def __init__(self, *args):并根据需要调用该代码fn

您提到了不同的参数列表,但没有描述如何区分它们。如果它是一个简单的标准,例如len(args),那么您所拥有的就足够了。如果它更复杂,您可能想要放入**kwargs签名,并让每个方法只挑选它识别的关键字参数。


查看完整回答
反对 回复 2021-09-14
  • 2 回答
  • 0 关注
  • 192 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信