猿问

__add__ 返回超类的实例而不是子类

当我对某个类进行子类int化并自定义它的__add__方法并调用super().__add__(other)它时,它会返回一个实例int,而不是我的子类。我可以通过在每个返回 an 的方法中的每次调用type(self)之前添加来解决这个问题,但这似乎过分了。必须有更好的方法来做到这一点。和s也会发生同样的事情。super()intfloatsfractions.Fraction


class A(int):

    def __add__(self, other):

        return super().__add__(other)


x = A()

print(type(x + 1))

输出:

<class 'int'>


预期输出:

<class '__main__.A'>


牧羊人nacy
浏览 153回答 3
3回答

慕尼黑的夜晚无繁华

这可以使用描述符来完成。以下类使用在类体内实例化该类时具有特殊效果的特殊方法。class SuperCaller:&nbsp; &nbsp; def __set_name__(self, owner, name):&nbsp; &nbsp; &nbsp; &nbsp; """Called when the class is defined. owner is the class that's being&nbsp; &nbsp; &nbsp; &nbsp; defined. name is the name of the method that's being defined.&nbsp; &nbsp; &nbsp; &nbsp; """&nbsp; &nbsp; &nbsp; &nbsp; method = getattr(super(owner, owner), name)&nbsp; &nbsp; &nbsp; &nbsp; def call(self, other):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Note that this self shadows the __set_name__ self. They are two&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # different things.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return type(self)(method(self, other))&nbsp; &nbsp; &nbsp; &nbsp; self._call = call&nbsp; &nbsp; def __get__(self, instance, owner):&nbsp; &nbsp; &nbsp; &nbsp; """instance is an instance of owner."""&nbsp; &nbsp; &nbsp; &nbsp; return lambda other: self._call(instance, other)class A(int):&nbsp; &nbsp; __add__ = SuperCaller()x = A()print(type(x + 1))输出:<class '__main__.A'>

偶然的你

一种方法是创建一个装饰器,它可以用强制转换包装所需的数学运算:def wrap_math(c):&nbsp; &nbsp; def wrapped(orig):&nbsp; &nbsp; &nbsp; &nbsp; return lambda s, o: c(orig(s,o))&nbsp; &nbsp; maths = ["__add__", "__sub__"]&nbsp; &nbsp; for op in maths:&nbsp; &nbsp; &nbsp; &nbsp; func = wrapped(getattr(c, op))&nbsp; &nbsp; &nbsp; &nbsp; setattr(c, op, func)return c@wrap_mathclass Special(int)&nbsp; &nbsp; pass&nbsp;x = Special(10)&nbsp;type(x + 10)完成您要包装的功能列表,您应该一切顺利。一种方法是创建一个装饰器,它可以用强制转换包装所需的数学运算:def wrap_math(c):&nbsp; &nbsp; def wrapped(orig):&nbsp; &nbsp; &nbsp; &nbsp; return lambda s, o: c(orig(s,o))&nbsp; &nbsp; maths = ["__add__", "__sub__"]&nbsp; &nbsp; for op in maths:&nbsp; &nbsp; &nbsp; &nbsp; func = wrapped(getattr(c, op))&nbsp; &nbsp; &nbsp; &nbsp; setattr(c, op, func)return c@wrap_mathclass Special(int)&nbsp; &nbsp; pass&nbsp;x = Special(10)&nbsp;type(x + 10)完成您要包装的功能列表,您应该一切顺利。

斯蒂芬大帝

该super()函数从父类调用方法,int在这种情况下。相反,您应该在方法中初始化类__add__:class A(int):&nbsp; &nbsp; def __add__(self, number):&nbsp; &nbsp; &nbsp; &nbsp; return A(self.numerator + number)x = A(4)print(type(x + 1))
随时随地看视频慕课网APP

相关分类

Python
我要回答