簡體   English   中英

__add__ 返回超類的實例而不是子類

[英]__add__ returns instance of superclass not subclass

當我將一些 class 子類化時,說int並自定義它的__add__方法並調用super().__add__(other)它返回一個int實例,而不是我的子類。 我可以通過在每個返回int的方法中的每個super()調用之前添加type(self)來解決這個問題,但這似乎太過分了。 必須有更好的方法來做到這一點。 floatsfractions.Fraction也會發生同樣的事情。

class A(int):
    def __add__(self, other):
        return super().__add__(other)

x = A()
print(type(x + 1))

Output:
<class 'int'>

預期 Output:
<class '__main__.A'>

這可以使用描述符來完成。 下面的 class 使用了特殊的方法,當 class 在 class 內部實例化時具有特殊效果。

class SuperCaller:

    def __set_name__(self, owner, name):
        """Called when the class is defined. owner is the class that's being
        defined. name is the name of the method that's being defined.
        """
        method = getattr(super(owner, owner), name)
        def call(self, other):
            # Note that this self shadows the __set_name__ self. They are two
            # different things.
            return type(self)(method(self, other))
        self._call = call

    def __get__(self, instance, owner):
        """instance is an instance of owner."""
        return lambda other: self._call(instance, other)


class A(int):
    __add__ = SuperCaller()


x = A()
print(type(x + 1))

Output: <class '__main__.A'>

一種方法是創建一個裝飾器,它可以用強制轉換包裝所需的數學運算:

def wrap_math(c):
    def wrapped(orig):
        return lambda s, o: c(orig(s,o))

    maths = ["__add__", "__sub__"]
    for op in maths:
        func = wrapped(getattr(c, op))
        setattr(c, op, func)

return c

@wrap_math
class Special(int)
    pass

 x = Special(10)
 type(x + 10)

完成您要包裝的功能列表,您應該對 go 很好。

super() function 從父 class 調用方法,在這種情況下是int 相反,您應該在__add__方法中初始化 class:

class A(int):
    def __add__(self, number):
        return A(self.numerator + number)

x = A(4)
print(type(x + 1))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM