今天我们来聊聊魔术方法使用的精髓,叫做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中的一个魔术方法,用于在两个对象相乘时调用。它接受两个参数:self
和other
,其中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
对象作为参数,并计算它们的矩阵乘积。
在这个例子中,我们首先创建了两个矩阵m1
和m2
,然后使用@
运算符将它们相乘,并将结果存储在变量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
,表示除数。如果 other
是 MyInt
类型的对象,则使用该对象的 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.value
和 other
的模运算结果。
然后,创建一个 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
对象a
和b
,分别表示数字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
属性。
当我们在 a
和 b
上执行按位与运算时,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__
方法需要返回一个新的对象,该对象表示self
和other
进行位运算或操作后的结果。
下面是一个简单的例子,演示了如何在自定义类中实现位运算或操作:
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.value
和 other.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
对象a
和b
,分别表示整数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。