How to create child class instance using some magic in parent __new__?

柔情痞子 提交于 2019-11-30 09:52:37

问题


For example, creating custom number types in following hierarchy

  • Number
    • Complex
    • Real
      • Int
      • Float

with logic in __new__ methods:

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

And then, creating Float instance using Number constructor:

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

This code will raise RuntimeError because of recursion limit. It is just example of desired behaviour. But I also tried to implement this using super and it is seems I misunderstand the world.


回答1:


Your Complex, Float and Int classes do not have __new__ methods, so they inherit these from Number; this is what is causing your infinite recursion.

You could test against the __class__ closure to see if you have a subclass or not:

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

and do the same in 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('Ты больше не можешь вести себя так!!!')

Demo:

>>> 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


来源:https://stackoverflow.com/questions/26524065/how-to-create-child-class-instance-using-some-magic-in-parent-new

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!