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

发布于 2021-01-29 15:01:35

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

  • 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,似乎我误解了世界。

关注者
0
被浏览
58
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看