怎么实现给抽象方法类增加__call__方法

2022-05-17 12:09:57 +08:00
 caneman

需求: 想给抽象方法类实现函数式调用,该怎么写

分开写,我知道怎么写,但是怎么让一个类同时具有两种特性?

抽象方法类

class A(ABC):

    def __init__(self, name):
        self.name = name

    @abstractmethod
    def run(self):
        pass


class B(A):

    def __init__(self, name):
        super().__init__(name)

    def run(self):
        print(self.name)


实现函数式调用

class MetaB(type):

    def __call__(cls, *args, **kwargs):
        obj = super().__call__(*args, **kwargs)
        return obj.run()

class B(metaclass=MetaB):

    def run(self):
        pass

怎么让 B 同时拥有两种特性?按我的理解要想让一个类实现函数式调用,就得在它的元类里面重载__call__方法,可是抽象方法类实现的过程中已经定义了元类是 ABCMeta ,这种情况该怎么覆写呢?

2032 次点击
所在节点    Python
7 条回复
BingoXuan
2022-05-17 12:15:35 +08:00
看了半天也没理解 lz 到底像要啥。你是希望如下还怎么样
b = B()
b.run()
b()
# b() has same effect like b.run()
caneman
2022-05-17 12:23:38 +08:00
@BingoXuan 我想实现的是,B 是一个类,但是可以当作函数用,B(),就直接执行了
fgwmlhdkkkw
2022-05-17 12:27:34 +08:00
__new__
caneman
2022-05-17 12:30:05 +08:00
@BingoXuan
大概这么一个场景,很多类,每个类有细微不同,把里面共同的部分提取出来,放在一个抽象类里面,也定义了一些子类必须实现的方法(代码 1 的部分)

所有这些子类,并不需要保持一个对象,可以看作一个大号的函数,我想实现,所有的子类,能通过 B() 这样就直接执行(代码 2 的部分)

有没有一种方法,能让 B 同时实现两种功能,即在 1 的基础上,让其子类能实现,子类()这样作为一个函数直接执行的功能
BingoXuan
2022-05-17 12:31:30 +08:00
@caneman
3 楼那样,__new__
调用顺序是 metaclass.__new__->metaclass.__init__->cls.__new__->cls.__init__
caneman
2022-05-17 12:39:58 +08:00
@BingoXuan 比__new__的时机要晚,在 cls.__init__之后(下面的代码不对,但是大概这么个意思)
caneman
2022-05-17 12:40:36 +08:00
class A(ABC):

def __call__(self, *args, **kwargs):
obj = super().__call__(*args, **kwargs)
return obj.run()

def __init__(self, name):
self.name = name

@abstractmethod
def run(self):
pass


class B(A):

def __init__(self, name):
super().__init__(name)

def run(self):
print(self.name)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/853415

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX