我们如何在仍然使用 `class` 关键字的同时覆盖构造函数? [复制]

Posted

技术标签:

【中文标题】我们如何在仍然使用 `class` 关键字的同时覆盖构造函数? [复制]【英文标题】:How can we override the constructor while still using the `class` keyword? [duplicate] 【发布时间】:2020-02-23 00:44:30 【问题描述】:

创建类的两种值得注意的方法如下所示:

class Klass:
    pass

Klass = type("Klass", tuple(), dict())

我想覆盖构造函数 (__call__),同时仍然使用 class 关键字,而不是做其他事情,比如直接调用 type。我真的很想覆盖 (__call__),而不是 __init__

我的失败尝试如下所示:

尝试 1

class Foo:
    @classmethod
    def __call__(*args):
        print("arr har")
        return super(type(args[0]), args[0]).__call__(*args)

instance = Foo()
# did not print "arr har"

尝试 2

class BarMeta(type):
    def __call__(*args):
        print("hello world")
        return super(type(args[0]), args[0]).__call__(*args[1:])

尝试 2A

class Bar:
    __metaclass__ = BarMeta

instance = Bar()
# did not print "hello world" 

尝试 2B

Baz = BarMeta("Baz", tuple(), dict())
instance = Baz()
# Did print "hello world," but we weren't able to use the `class` keyword to create `Baz`

【问题讨论】:

但是__call__ 不是他的构造函数,__new__ 是。如果你想覆盖__call__,你所要做的就是覆盖__call__ 如果您使用的是 python 2,尝试 2A 将起作用。在 python 3 中,定义元类的语法是 class Bar(metaclass=BarMeta): @DeepSpace 但是__call__ 调用__new__,而不是相反。 instance = Klass()instance = Klass.__call__()instance = type(Klass).__call__(Klass) 相同 另外,我(显然至少还有另外两个人)很难理解您的问题。最好先明确说明您想要做什么,即“我希望 Bar() 打印 'arr har'”。 @DeepSpace type.__call__ 确实是唯一的例子。 repl.it/repls/EvenSandyPress 【参考方案1】:

所有功劳归于Aran-Fey,他将答案作为评论而不是作为答案发布:

class BarMeta(type):
    def __call__(*args):
        print("hello world")
        return super(type(args[0]), args[0]).__call__(*args[1:])    

class Bar(metaclass=BarMeta):
    pass

instance = Bar()

【讨论】:

以上是关于我们如何在仍然使用 `class` 关键字的同时覆盖构造函数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

论文 | 绝缘子覆冰厚度图像识别

leetcode-76 最小覆盖子串

Java 中的“final”关键字是如何工作的? (我仍然可以修改对象。)

面向对象之接口

如何在仍然使用 Dagger2 的同时解决循环依赖?

JS继承之extends