如何使用类方法而不是调用构造函数来初始化父类?

Aar*_*ndt 5 python python-3.x

我有一个我想继承的类 A,这个类有一个类方法,可以从一些数据初始化一个新实例。我无权访问 A 的代码from_data,也无法更改 A 的实现。

我想使用传递给 Afrom_data方法的相同数据来初始化 B 类的新实例。在我提出的解决方案中,我创建了 A 的新实例 __new__(...)并将其更改__class__为 B。__init__(...)然后可以像平常一样进一步初始化“B 的新实例”。它似乎有效,但我不确定这会产生某种副作用。

那么这会可靠地工作吗?有没有正确的方法来实现这一目标?

class A:
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta

    @classmethod
    def from_data(cls, data):
        obj = cls(*data)
        return obj


class B(A):
    def __new__(cls, data):
        a = A.from_data(data)
        a.__class__ = cls
        return a

    def __init__(self, data):
        pass


b = B((5, 3))
print(b.alpha, b.beta)
print(type(b))
print(isinstance(b, B))
Run Code Online (Sandbox Code Playgroud)

输出:

5 3
<class '__main__.B'>
True
Run Code Online (Sandbox Code Playgroud)

Spa*_*029 0

可能你的用例比我理解的更抽象,但是在 REPL 中测试,似乎通过调用父class A构造函数super()

class A:
    # ...


class B(A):
    def __init__(self, data):
        super().__init__(*data)


b = B((5, 3))
print(b.alpha, b.beta)
print(type(b))
print(isinstance(b, B))
Run Code Online (Sandbox Code Playgroud)

也导致

5 3
<class '__main__.B'>
True
Run Code Online (Sandbox Code Playgroud)

您是否有理由不想调用super()来实例化子类的新实例?


编辑:

所以,如果你需要使用from_data构造函数......你可以做类似的事情

#... class A

class B(A):
    def __init__(self, data):
        a_obj = A.from_data(data)
        for attr in a_obj.__dict__:
            setattr(self, attr, getattr(a_obj, attr))
Run Code Online (Sandbox Code Playgroud)

但这确实很hacky...并且不能保证适用于A类对象的所有属性,特别是在__dict__函数已重载的情况下。