今天我们来聊聊魔术方法使用的精髓,叫做emulation。我们知道python中的类型系统叫做duck type。

简单的说,就是他不去检查具体的这个对象是什么类型,而是检查这个对象有没有响应的功能。

而python中有大量的魔术方法,就是给某一个对象加上相应的功能,接下来聊一聊emulating numeric types,也就是让你的类型实现一些数的功能。

__add__魔术方法

__add__是一种在Python中定义对象之间加法操作的魔术方法。当使用“+”运算符对两个对象执行加法操作时,Python将会查找并调用每个对象中定义的__add__方法。

以下是一个简单的例子,其中我们定义了一个名为MyNumber的类,并定义了__add__方法来允许在对象之间执行加法操作:


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

    def __add__(self, other):
        if isinstance(other, MyNumber):
            return MyNumber(self.value + other.value)
        elif isinstance(other, (int, float)):
            return MyNumber(self.value + other)
        else:
            return NotImplemented

    def __repr__(self):
        return f"MyNumber({self.value})"


n1 = MyNumber(1)
n2 = MyNumber(2)
print(n1 + n2)
print(n1 + 5)
print(n2 + "3")

输出结果为:

Traceback (most recent call last):
  File "/mnt/f/lianhaifeng_codes/djangoProject/djangoProject/sss.py", line 21, in <module>
    print(n2 + "3")
TypeError: unsupported operand type(s) for +: 'MyNumber' and 'str'
MyNumber(3)
MyNumber(6)

__iadd__魔术方法

__iadd__是Python中的一个魔术方法,用于在类中定义就地加法的实现,即将两个对象相加,并将结果存储在第一个对象中。在Python中,就地加法使用+=运算符进行实现,如果类中没有实现__iadd__,则Python解释器会尝试使用__add__方法代替__iadd__方法,这样会创建一个新的对象并返回结果。

以下是一个使用__iadd__方法的示例:

class MyList:
    def __init__(self, items):
        self.items = items

    def __iadd__(self, other):
        if isinstance(other, MyList):
            self.items.extend(other.items)
        else:
            self.items.append(other)
        return self

    def __repr__(self):
        return f'MyList({self.items})'


l1 = MyList([1, 2, 3])
l2 = MyList([4, 5, 6])
l1 += l2  # 就地加法
print(l1)  # 输出 MyList([1, 2, 3, 4, 5, 6])

在上面的示例中,MyList类实现了__iadd__方法,用于将两个MyList对象进行就地加法。当执行l1 += l2时,l1对象的__iadd__方法被调用,将l2对象的内容添加到l1中,最终结果存储在l1中。

需要注意的是,__iadd__方法需要返回self对象,以便在就地加法完成后继续使用当前对象。

__sub__魔术方法

__sub__是一个魔术方法,用于定义两个对象相减的行为。当对象使用 - 运算符进行相减操作时,会自动调用 __sub__ 方法。

下面是一个例子,展示了如何定义一个自定义对象的 __sub__ 方法:

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

    def __sub__(self, other):
        return MyNumber(self.value - other.value)

    def __repr__(self):
        return f"MyNumber({self.value})"


a = MyNumber(10)
b = MyNumber(5)
c = a - b
print(c)  # 输出 MyNumber(5)

__mul__魔术方法

__mul__是Python中的一个魔术方法,用于在两个对象相乘时调用。它接受两个参数:selfother,其中self是调用方法的对象,而other是传递给方法的参数。

下面是一个简单的例子,展示了如何使用__mul__方法重载乘法运算符:

class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __mul__(self, other):
        return MyClass(self.value * other)

x = MyClass(10)
y = x * 2
print(y.value)  # 输出 20

__rmul__魔术方法

__rmul__魔术方法是指右侧乘法运算的魔术方法。当一个对象被用于乘法运算并且它是另一个对象的右侧操作数时,Python会尝试调用它的__rmul__方法来进行运算。

例如,在下面的代码中,我们创建了一个自定义的类MyInt,它包含一个整数值,并实现了__rmul__方法:

class MyInt:
    def __init__(self, value):
        self.value = value
    
    def __rmul__(self, other):
        return MyInt(self.value * other)

x = MyInt(10)
result = 5 * x
print(result.value)  # 输出 50

在上面的例子中,Python首先将5作为参数传递给__rmul__方法,因此other参数的值为5。__rmul__方法将MyInt对象的值与other参数相乘,并返回一个新的MyInt对象,其值为乘积。最后,结果被赋给result变量,并打印出来。

需要注意的是,在__rmul__方法中,我们必须返回一个新的对象,而不能修改原始对象的值。这是因为Python的乘法运算符是不可变的,所以我们不能直接在原始对象上修改它的值。

__matmul__魔术方法

__matmul__是一个魔术方法,用于定义对象的“@”运算符。当我们使用“@”运算符时,Python 会自动调用该对象的__matmul__方法。

例如,我们可以定义一个Matrix类,并在其中实现__matmul__方法来定义矩阵相乘的操作。以下是一个简单的示例:

class Matrix:
    def __init__(self, data):
        self.data = data
    
    def __matmul__(self, other):
        if not isinstance(other, Matrix):
            raise TypeError('Operand must be a matrix')
        if len(self.data[0]) != len(other.data):
            raise ValueError('Matrix dimensions do not match')
        result = [[0] * len(other.data[0]) for _ in range(len(self.data))]
        for i in range(len(self.data)):
            for j in range(len(other.data[0])):
                for k in range(len(other.data)):
                    result[i][j] += self.data[i][k] * other.data[k][j]
        return Matrix(result)
        
m1 = Matrix([[1, 2], [3, 4]])
m2 = Matrix([[5, 6], [7, 8]])
result = m1 @ m2
print(result.data) # 输出 [[19, 22], [43, 50]]

在这个例子中,Matrix类具有一个属性data,它是一个二维列表,代表矩阵中的数据。__matmul__方法接受另一个Matrix对象作为参数,并计算它们的矩阵乘积。

在这个例子中,我们首先创建了两个矩阵m1m2,然后使用@运算符将它们相乘,并将结果存储在变量result中。最后,我们打印了结果矩阵的数据。

__truediv__魔术方法

__truediv__是Python中的一个魔术方法,用于实现对象除法运算。当使用“/”符号时,会自动调用该方法。需要注意的是,该方法仅适用于Python 3.x及以上版本。

以下是一个示例:

class Fraction:
    def __init__(self, numerator, denominator):
        self.numerator = numerator
        self.denominator = denominator

    def __truediv__(self, other):
        numerator = self.numerator * other.denominator
        denominator = self.denominator * other.numerator
        return Fraction(numerator, denominator)

    def __str__(self):
        return f"{self.numerator}/{self.denominator}"

f1 = Fraction(1, 2)
f2 = Fraction(2, 3)
f3 = f1 / f2
print(f3)  # 输出: 3/4

在上面的示例中,Fraction类定义了__truediv__方法,该方法将两个分数相除并返回一个新的Fraction对象。通过使用“/”符号,我们可以使用__truediv__方法实现分数之间的除法运算。

__floordiv__魔术方法

__floordiv__ 是 Python 中的一个魔术方法,用于实现整数除法运算。当使用 // 运算符进行整数除法时,Python 会自动调用对象的 __floordiv__ 方法来完成运算。如果对象没有实现该方法,则会引发 TypeError 异常。

下面是一个示例,展示如何实现 __floordiv__ 方法:

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

    def __floordiv__(self, other):
        if isinstance(other, MyInt):
            return MyInt(self.value // other.value)
        elif isinstance(other, int):
            return MyInt(self.value // other)
        else:
            return NotImplemented

    def __str__(self):
        return str(self.value)


x = MyInt(10)
y = MyInt(3)
z = x // y
print(z)  # 输出 "3"

在上面的代码中,MyInt 类实现了 __floordiv__ 方法,该方法接受一个参数 other,表示除数。如果 otherMyInt 类型的对象,则使用该对象的 value 属性进行整数除法运算,否则将 other 转换为整数进行运算。如果 other 的类型不是 MyInt 或整数,则返回 NotImplemented,这表示无法处理该类型的对象。

__mod__魔术方法

__mod__ 是 Python 中的一个魔术方法,用于定义 % 运算符的行为。当对一个对象使用 % 运算符时,如果该对象的类中定义了 __mod__ 方法,则会调用该方法进行运算。

例如:

class MyNumber:
    def __init__(self, value):
        self.value = value
        
    def __mod__(self, other):
        return self.value % other
    
n = MyNumber(7)
result = n % 3
print(result)  # 输出 1

上面的代码中,定义了一个 MyNumber 类,并在其中实现了 __mod__ 方法。该方法返回 self.valueother 的模运算结果。

然后,创建一个 MyNumber 对象 n,并对它使用 % 运算符进行运算。由于 MyNumber 类定义了 __mod__ 方法,所以 Python 会自动调用该方法进行运算。最终的结果是 1

需要注意的是,如果在 __mod__ 方法中,other 参数的类型与 self 不兼容,会抛出 TypeError 异常。如果 other 参数为零,会抛出 ZeroDivisionError 异常。

__divmod__魔术方法

__divmod__是一个魔术方法,用于在进行除法运算时同时返回商和余数。该方法需要实现两个参数:除数和被除数。在运算时,Python会自动调用__divmod__方法,并将除数和被除数作为参数传递给该方法,然后根据方法返回值计算商和余数。

__divmod__方法的返回值应该是一个元组,其中包含商和余数。

以下是一个示例:

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

    def __divmod__(self, other):
        quotient = self.value // other.value
        remainder = self.value % other.value
        return quotient, remainder

num1 = MyNumber(10)
num2 = MyNumber(3)
print(divmod(num1, num2)) # 输出 (3, 1)

在上面的示例中,我们定义了一个MyNumber类,该类具有一个value属性,代表数字的值。我们还实现了__divmod__方法,该方法接收两个参数,并使用//%运算符来计算商和余数。我们使用内置的divmod函数来调用该方法,并将其应用于两个MyNumber对象。函数的返回值是一个元组,包含商和余数。

__pow__魔术方法

__pow__是一个魔术方法,用于指定一个类实例作为指数时如何进行幂运算。它接受两个参数,分别为底数和指数,返回底数的指数次幂。

示例代码:

class MyClass:
    def __init__(self, val):
        self.val = val

    def __pow__(self, other):
        return self.val ** other

obj = MyClass(3)
print(obj ** 2)  # 输出 9
print(pow(obj, 3))  # 输出 27

在上面的示例中,我们定义了一个名为MyClass的类,它有一个实例属性val,并实现了__pow__方法。该方法将实例作为底数,接受一个整数类型的参数作为指数,并返回底数的指数次幂。

我们创建了一个MyClass的实例obj,然后用**符号对它进行了幂运算,并打印结果。也可以使用内置的pow()函数进行幂运算,将实例和指数作为参数传递给该函数。

需要注意的是,如果指数不是整数类型,Python 会自动将其转换为浮点数类型,而不是调用__pow__方法进行幂运算。

__lshift__魔术方法

__lshift__是Python中的魔术方法,用于实现按位左移运算符<<的操作,即将一个数的二进制表示向左移动指定的位数。

在使用<<时,如果左边的操作数是一个对象,那么Python会调用该对象的__lshift__方法来完成移位运算。

__lshift__方法接收一个整数参数,表示要左移的位数,返回一个新的对象,表示移位后的结果。

下面是一个例子,展示如何实现__lshift__方法:

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

    def __lshift__(self, other):
        return MyNumber(self.value << other)

    def __repr__(self):
        return str(self.value)

在上面的例子中,MyNumber类实现了__lshift__方法,该方法接收一个整数参数other,表示要左移的位数。__lshift__方法将self.value向左移动other位,并返回一个新的MyNumber对象,表示移位后的结果。

我们可以创建一个MyNumber对象,并对其进行左移运算:

>>> x = MyNumber(10)
>>> x
10
>>> y = x << 2
>>> y
40

在上面的代码中,我们首先创建一个MyNumber对象x,其值为10。然后,我们对x进行左移运算,并将结果赋值给y。左移运算的位数为2,因此y的值为40

__rshift__魔术方法

__rshift__是一种魔术方法,用于实现位运算右移操作(>>)。

当对一个对象进行位运算右移操作时,如果该对象所属的类实现了__rshift__方法,那么Python解释器就会调用该方法来执行右移操作。__rshift__方法应当返回右移后的结果。

下面是一个例子:

class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __rshift__(self, other):
        return MyNumber(self.value >> other.value)
    
    def __repr__(self):
        return f"MyNumber({self.value})"

a = MyNumber(8)
b = MyNumber(2)
print(a >> b) # 输出 MyNumber(2)

在这个例子中,我们定义了一个名为MyNumber的类,该类只有一个实例属性value。该类实现了__rshift__方法,用于执行位运算右移操作。

我们创建了两个MyNumber对象ab,分别表示数字8和2。然后,我们对a执行右移操作,并传递b作为右操作数。由于MyNumber实现了__rshift__方法,Python解释器会调用该方法来执行右移操作。__rshift__方法返回了一个新的MyNumber对象,其value属性值为8右移2位后的结果2。最终,我们打印出了这个新的MyNumber对象。

__and__魔术方法

__and__是Python中的一个魔术方法,用于重载位运算符 &,实现按位与运算。

例如,假设我们有一个自定义类 MyNumber,希望在该类中实现位运算操作,可以通过重载 __and__ 方法来实现按位与运算。下面是一个简单的示例:

class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __and__(self, other):
        return self.value & other.value

a = MyNumber(3)
b = MyNumber(5)
print(a & b) # 输出 1,因为 0b011 & 0b101 = 0b001

在这个例子中,我们在 MyNumber 类中重载了 __and__ 方法,以便将按位与运算委托给 int 类型的 value 属性。

当我们在 ab 上执行按位与运算时,Python将自动调用 a.__and__(b) 方法,并将结果返回。在这个例子中,由于 a.value 是 3(二进制为 0b011),b.value 是 5(二进制为 0b101),所以 a & b 的结果是 1(二进制为 0b001)。

__or__魔术方法

__or__是一个魔术方法,用于实现位运算或(or)操作。当在自定义类上使用二进制操作符|时,Python 解释器将调用该类中定义的__or__方法。

下面是__or__方法的基本语法:

class MyClass:
    def __or__(self, other):
        # 实现位运算或(or)操作的代码
        pass

在自定义类中,__or__方法接收两个参数,分别是实例对象 self 和另一个对象 other__or__方法需要返回一个新的对象,该对象表示selfother进行位运算或操作后的结果。

下面是一个简单的例子,演示了如何在自定义类中实现位运算或操作:

class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __or__(self, other):
        return MyNumber(self.value | other.value)
    
    def __str__(self):
        return str(self.value)

a = MyNumber(3)
b = MyNumber(6)

print(a | b)  # 输出 7

在上面的例子中,我们定义了一个MyNumber类,该类用于表示整数。我们定义了__or__方法,该方法实现了位运算或操作。在该方法中,我们将 self.valueother.value 进行位运算或操作,并返回一个新的 MyNumber 对象,其 value 属性为运算结果。最后,我们使用|操作符来调用__or__方法,该操作符返回了一个新的MyNumber对象,表示两个整数进行位运算或操作的结果。

值得注意的是,如果在自定义类上使用位运算或操作符时,另一个操作数不是与该类兼容的对象类型,则 Python 解释器会抛出TypeError异常。

__xor__魔术方法

__xor__是一个魔术方法,用于实现按位异或运算符^。它接受两个参数,分别是运算符左侧和右侧的操作数。当使用^运算符时,会自动调用__xor__方法进行计算,其返回值即为运算结果。

例如,假设我们定义了一个名为MyInt的类来模拟整数,可以实现__xor__方法来支持按位异或运算:

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

    def __xor__(self, other):
        return MyInt(self.value ^ other.value)

    def __repr__(self):
        return str(self.value)

在这个例子中,__xor__方法接受两个MyInt类型的实例作为参数,将它们的value属性进行异或运算,并返回一个新的MyInt实例。

下面是一些使用__xor__方法的示例:

>>> a = MyInt(3)
>>> b = MyInt(5)
>>> c = a ^ b
>>> c
6

在这个例子中,我们创建了两个MyInt对象ab,分别表示整数3和5。然后使用^运算符对它们进行按位异或运算,并将结果赋值给变量c。由于__xor__方法返回的是一个新的MyInt实例,因此变量c的值为整数6。

需要注意的是,__xor__方法并不会改变操作数本身的值,它只返回运算结果。如果我们希望将运算结果赋值给某个变量,需要显式进行赋值操作。

__neg__魔术方法

__neg__是Python中的一个魔术方法,用于定义一元负号运算符(-)的行为。当一个对象被应用一元负号运算符时,Python会调用这个对象的__neg__方法来进行计算并返回结果。

__neg__方法需要返回一个新的对象,它表示这个对象被取相反数后的结果。如果不想支持一元负号运算符,可以不实现__neg__方法,或者让它返回NotImplemented

下面是一个简单的示例,展示了如何定义__neg__方法:

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

    def __neg__(self):
        return MyClass(-self.value)

x = MyClass(10)
y = -x
print(y.value)  # 输出 -10

在这个例子中,MyClass类包含一个value属性。当一个MyClass实例被应用一元负号运算符时,__neg__方法会将其value属性取相反数,并返回一个新的MyClass实例。

__pos__魔术方法

__pos__是一个一元运算符魔术方法,用于对对象进行一元正运算(即取正数)。该方法需要返回一个对象,表示对输入对象进行一元正运算后的结果。

举个例子,我们可以定义一个名为MyNumber的类,并在其中实现__pos__方法,使其支持一元正运算:

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

    def __pos__(self):
        return MyNumber(abs(self.value))

在上面的代码中,我们定义了一个MyNumber类,它有一个实例变量value,表示数字的值。我们实现了__pos__方法,它返回一个新的MyNumber对象,表示输入对象取正数的结果。

现在,我们可以创建一个MyNumber对象,并对它进行一元正运算,如下所示:

n = MyNumber(-10)
p = +n
print(p.value)  # 输出 10

在上面的代码中,我们创建了一个MyNumber对象n,它的值为-10。然后,我们对n进行一元正运算,得到一个新的MyNumber对象p,它的值为10。

__abs__魔术方法

__abs__ 是 Python 中的一个魔术方法,用于定义对象的绝对值计算方式。

当对一个对象调用内置函数 abs() 时,如果该对象定义了 __abs__ 方法,那么 __abs__ 方法就会被调用,用于计算该对象的绝对值,返回一个非负数的结果。

以下是一个 __abs__ 方法的示例,它定义了自定义类型 MyNumber 对象的绝对值的计算方式:

class MyNumber:
    def __init__(self, x):
        self.x = x
    
    def __abs__(self):
        return abs(self.x)

在上述代码中,MyNumber 类定义了一个名为 __abs__ 的魔术方法,当调用内置函数 abs() 时,该方法就会被调用,用于计算 MyNumber 对象的绝对值。

以下是使用 MyNumber 对象调用内置函数 abs() 的示例:

x = MyNumber(-3)
print(abs(x))  # 输出 3

在上述代码中,我们创建了一个 MyNumber 对象 x,它的实例变量 x 的值为 -3。我们使用 abs() 函数计算 x 的绝对值,该调用将会调用 x 对象的 __abs__ 方法,并返回 3 作为结果。

__invert__魔术方法

__invert__是Python中的一个魔术方法,用于实现按位取反(bitwise inversion)。该方法只接受一个self参数,返回值为按位取反后的结果。

在Python中,按位取反的操作符为~,可以通过实现__invert__方法来自定义该操作符的行为。例如,下面的代码演示了如何实现自定义的按位取反:

class MyNumber:
    def __init__(self, value):
        self.value = value
        
    def __invert__(self):
        return ~self.value

n = MyNumber(10)
print(~n)  # 输出 -11

在上面的代码中,我们定义了一个MyNumber类,并实现了__invert__方法,该方法返回按位取反后的结果。当我们创建一个MyNumber实例并使用按位取反操作符~时,Python会自动调用该实例的__invert__方法,并返回按位取反后的结果。

__complex__魔术方法

__complex__是Python中的一个魔术方法,用于定义一个对象被转换为复数时的行为。该方法需要返回一个复数。

如果一个对象没有定义该方法,当该对象被转换为复数时会引发TypeError异常。

下面是一个示例:

class MyNumber:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag
    
    def __complex__(self):
        return complex(self.real, self.imag)

num = MyNumber(1, 2)
print(complex(num)) # 输出 (1+2j)

在这个示例中,我们定义了一个名为MyNumber的类,它包含一个real和一个imag属性。当MyNumber的实例被转换为复数时,会调用__complex__方法并返回一个复数对象。我们在该方法中使用了内置函数complex()来生成一个复数对象。最后,我们将一个MyNumber实例传递给complex()函数并打印返回的复数对象。

注意,__complex__方法不会修改MyNumber实例本身,它只是返回一个新的复数对象。

__int__魔术方法

__int__是一个Python的魔术方法,用于自定义类的实例被转换为整数时的行为。当使用int()函数显式地将自定义类的实例转换为整数时,将调用这个方法。

以下是一个示例:

class MyInt:
    def __init__(self, num):
        self.num = num

    def __int__(self):
        return self.num

a = MyInt(10)
print(int(a))   # 输出10

在上面的示例中,我们自定义了一个名为MyInt的类,并定义了一个__int__方法。这个方法接受一个参数num,并将其返回,使得MyInt类的实例可以被显式地转换为整数类型。当我们使用int()函数将MyInt类的实例a转换为整数时,它将调用a对象的__int__方法,并返回其num属性值10。

__float__魔术方法

__float__是一个魔术方法,用于将对象转换为浮点数。当调用float(obj)时,实际上会调用obj.__float__()方法。如果对象不支持浮点数转换,则会引发TypeError异常。

下面是一个简单的示例:

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

    def __float__(self):
        return float(self.value)


n = MyNumber(3)
print(float(n))  # 输出 3.0

在上面的示例中,我们定义了一个名为MyNumber的类,并实现了__float__方法来支持浮点数转换。__float__方法将self.value转换为浮点数并返回。最后,我们创建了一个MyNumber对象n,并将其传递给float函数进行转换。最终,将输出浮点数3.0。

__index__魔术方法

__index__是一种特殊的方法,它用于返回一个整数,该整数表示对象的“索引”(通常表示为该对象在某个序列中的位置)。

当我们使用内置函数bin(),oct(),hex()等转换函数时,Python会自动调用对象的__index__方法,来返回一个整数表示对象在二进制、八进制、十六进制等表示方法下的值。

例如,对于一个自定义类,我们可以通过实现__index__方法,使其支持转换成二进制、八进制和十六进制字符串,示例如下:

class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __index__(self):
        return self.value
        
    def __str__(self):
        return str(self.value)
        

my_number = MyNumber(42)
print(bin(my_number))   # 输出 0b101010
print(oct(my_number))   # 输出 0o52
print(hex(my_number))   # 输出 0x2a

在上面的示例中,我们实现了__index__方法来返回对象的整数表示。当我们在使用bin(),oct(),hex()函数时,Python会自动调用该方法,并返回对应进制的字符串表示。

__round__魔术方法

__round__ 是一个魔术方法,它定义了当对象通过内置的 round() 函数进行四舍五入时应该执行的操作。该方法应该返回一个被四舍五入后的数字,或者 None

这个方法的调用方式是通过内置的 round() 函数进行的,传入需要进行四舍五入的数字作为第一个参数,可选的第二个参数为保留的小数位数(默认为 None),以及可选的第三个参数 ndigits(默认为 None),用于指定十进制数字的精度。

下面是一个示例,展示了如何定义一个自定义类并使用 __round__ 方法:

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

    def __round__(self, n=None):
        if n is None:
            return round(self.value)
        else:
            return round(self.value, n)


num = MyNumber(3.14159)
print(round(num))   # 输出 3
print(round(num, 2))   # 输出 3.14

在上面的示例中,我们定义了一个名为 MyNumber 的类,其中 __round__ 方法使用 round() 函数将类中的 value 属性四舍五入到给定的小数位数。在示例中,我们首先创建一个 MyNumber 对象,并将其传递给内置的 round() 函数。由于没有指定小数位数,因此 __round__ 方法将 value 属性四舍五入到最接近的整数。接下来,我们传递一个小数位数为 2 的值给 round() 函数,它将调用 __round__ 方法,并返回 value 属性被四舍五入到两位小数的值。

__trunc__魔术方法

__trunc__是一个魔术方法,用于实现对Python对象的截断整数运算。它在调用内置函数math.trunc()或使用内置函数trunc()时调用。

该方法返回一个整数,表示对象截断为整数后的值。如果对象已经是整数,则返回对象本身。如果对象无法表示为整数,则会引发TypeError异常。

下面是一个例子,说明如何使用__trunc__方法:

import math


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

    def __trunc__(self):
        return int(self.value)


num1 = MyNumber(3.14)
num2 = MyNumber(5)

print(math.trunc(num1))  # 输出 3
print(math.trunc(num2))  # 输出 5
print(math.trunc(num1))  # 输出 3
print(math.trunc(num2))  # 输出 5

在上面的例子中,我们定义了一个名为MyNumber的类,并实现了__trunc__方法。__trunc__方法将浮点数值转换为整数,然后返回整数值。在调用内置函数math.trunc()或使用内置函数trunc()时,会自动调用__trunc__方法。最后,我们打印了截断后的值。

__floor__魔术方法

__floor__ 是一个魔术方法,用于支持 Python 的内置函数 math.floor()cmath.floor()。它可以返回小于或等于当前数的最大整数。

这个方法应该返回一个整数或者一个对象,它的 __int__ 方法可以返回一个整数。如果 __floor__ 方法返回浮点数,则它将被自动转换为整数。

以下是一个简单的例子,展示了如何实现 __floor__ 方法:

import math

class MyNumber:
    def __init__(self, value):
        self.value = value
        
    def __floor__(self):
        return math.floor(self.value)

# 测试
my_number = MyNumber(3.5)
print(math.floor(my_number)) # 输出 3

在这个例子中,我们定义了一个 MyNumber 类,它包含一个实例变量 value。我们实现了 __floor__ 方法,使用 Python 的内置 math.floor() 函数来返回小于或等于 value 的最大整数。然后,我们创建了一个 MyNumber 对象 my_number,并使用 math.floor() 函数调用它的 __floor__ 方法,输出了结果 3。

__ceil__魔术方法

__ceil__是Python中的一个魔术方法,用于返回当前对象的向上取整值。它是Python内置的数学函数,对于支持向上取整的对象(如浮点数),可以通过使用math.ceil()函数轻松实现。

该方法需要定义在一个对象中,并在调用内置的ceil()函数时自动调用。

下面是一个使用__ceil__方法的例子,实现了一个MyNumber类,支持向上取整:

import math

class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __ceil__(self):
        return math.ceil(self.value)

num = MyNumber(2.3)
print(math.ceil(num)) # 输出 3

在这个例子中,MyNumber类包含了一个值(value),用于存储需要进行向上取整操作的数字。通过在这个类中实现__ceil__方法,我们可以使用内置的ceil()函数来调用该方法,并返回向上取整的结果。

在上面的例子中,我们首先创建了一个MyNumber对象num,该对象包含一个值2.3。然后,我们调用math.ceil()函数,它自动调用了num__ceil__方法,并返回向上取整后的结果3。

01-06 13:30