小编典典

如何使用父__new__中的一些魔术来创建子类实例?

python

例如,在以下层次结构中创建自定义数字类型

  • Number
    • Complex
    • Real
    • Int
    • Float

__new__方法中具有逻辑:

class Number:
    def __new__(cls, value):
        if isinstance(value, complex):
            return Complex(value)
        elif isinstance(value, (int, float)):
            return Real(value)
        else:
            raise TypeError('Ну ты и мудак!!!')

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


class Complex(Number):
    pass


class Real(Number):
    def __new__(cls, value):
        if isinstance(value, int):
            return Int(value)
        elif isinstance(value, float):
            return Float(value)
        else:
            raise TypeError('Ты больше не можешь вести себя так!!!')


class Int(Real):
    pass


class Float(Real):
    pass

然后,Float使用Number构造函数创建实例:

number = Number(6.6)
assert isinstance(number, Float)

RuntimeError由于递归限制,此代码将提高。这只是期望行为的示例。但是我也尝试使用这种方法来实现super,似乎我误解了世界。


阅读 146

收藏
2021-01-20

共1个答案

小编典典

ComplexFloatInt类也 不能__new__方法,让他们继承这些从Number; 这就是导致您无限递归的原因。

您可以针对__class__闭包进行测试,以查看是否具有子类:

class Number:
    def __new__(cls, value):
        if cls is not __class__:
            # Subclass, create an instance (invokes object.__new__)
            return super().__new__(cls)

        if isinstance(value, complex):
            return Complex(value)
        elif isinstance(value, (int, float)):
            return Real(value)
        else:
            raise TypeError('Ну ты и мудак!!!')

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

并在Real

class Real(Number):
    def __new__(cls, value):
        if cls is not __class__:
            # Subclass, create an instance
            return super().__new__(cls, value)

        if isinstance(value, int):
            return Int(value)
        elif isinstance(value, float):
            return Float(value)
        else:
            raise TypeError('Ты больше не можешь вести себя так!!!')

演示:

>>> class Number:
...     def __new__(cls, value):
...         if cls is not __class__:
...             # Subclass, create an instance
...             return super().__new__(cls)
...         if isinstance(value, complex):
...             return Complex(value)
...         elif isinstance(value, (int, float)):
...             return Real(value)
...         else:
...             raise TypeError('Ну ты и мудак!!!')
...     def __init__(self, value):
...         self.value = value
... 
>>> class Real(Number):
...     def __new__(cls, value):
...         if cls is not __class__:
...             # Subclass, create an instance
...             return super().__new__(cls, value)
...         if isinstance(value, int):
...             return Int(value)
...         elif isinstance(value, float):
...             return Float(value)
...         else:
...             raise TypeError('Ты больше не можешь вести себя так!!!')
... 
>>> class Complex(Number):
...     pass
... 
>>> class Int(Real):
...     pass
... 
>>> class Float(Real):
...     pass
... 
>>> number = Number(6.6)
>>> isinstance(number, Float)
True
2021-01-20