一、什么是魔术方法?
魔术方法是特殊方法的昵称。特殊方法也叫双下方法。类似这样:__getitem__
二、使用特殊方法示例
from math import hypot
# 二维向量类
# 自定义特殊方法
class Vector(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return 'Vector(%r,%r)' % (self.x, self.y)
def __abs__(self):
return hypot(self.x, self.y)
def __mul__(self, other):
return Vector(self.x * other, self.y * other)
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Vector(x, y)
a = Vector(3, 4)
b = Vector(1, 2)
print(abs(a), a * 3)
print(a + b)
三、特殊方法汇总
1、非数学运算
①、 字符串表示
__repr__
__str__
②、 集合、序列相关
__len__
__getitem__
__setitem__
__delitem__
__contains__
③、迭代相关
__iter__
__next__
④、可调用
__call__
⑤、with上下文管理器
__enter__
__exit__
⑥、数值转换
__abs__
__bool__
__int__
__float__
__hash__
__index__
⑦、元类相关
__new__
__init__
⑧、属性相关
__getattr__、 __setattr__
__getattribute__、setattribute__
__dir__
⑨、属性描述符
__get__、__set__、 __delete__
⑩、协程
__await__、__aiter__、__anext__、__aenter__、__aexit__
2、数学运算
① 一元运算符
__neg__(-)、__pos__(+)、__abs__
②二元运算符
__lt__(<)、 __le__ <= 、 __eq__ == 、 __ne__ != 、 __gt__ > 、 __ge__ >=
③算术运算符
__add__ + 、 __sub__ - 、 __mul__ * 、 __truediv__ / 、 __floordiv__ // 、 __mod__ % 、 __divmod__ divmod() 、 __pow__ ** 或 pow() 、 __round__ round()
④反向算术运算符
__radd__ 、 __rsub__ 、 __rmul__ 、 __rtruediv__ 、 __rfloordiv__ 、 __rmod__ 、__rdivmod__ 、 __rpow__
⑤增量赋值算术运算符
__iadd__ 、 __isub__ 、 __imul__ 、 __itruediv__ 、 __ifloordiv__ 、 __imod__ 、__ipow__
⑥位运算符
__invert__ ~ 、 __lshift__ << 、 __rshift__ >> 、 __and__ & 、 __or__ | 、 __xor__ ^
⑦反向位运算符
__rlshift__ 、 __rrshift__ 、 __rand__ 、 __rxor__ 、 __ror__
⑧增量赋值位运算符
__ilshift__ 、 __irshift__ 、 __iand__ 、 __ixor__ 、 __ior__
⑨一元运算符
__neg__(-)、__pos__(+)、__abs__
⑩二元运算符
__lt__(<)、 __le__ <= 、 __eq__ == 、 __ne__ != 、 __gt__ > 、 __ge__ >=
11算术运算符
__add__ + 、 __sub__ - 、 __mul__ * 、 __truediv__ / 、 __floordiv__ // 、 __mod__ % 、 __divmod__ divmod() 、 __pow__ ** 或 pow() 、 __round__ round()
12反向算术运算符
__radd__ 、 __rsub__ 、 __rmul__ 、 __rtruediv__ 、 __rfloordiv__ 、 __rmod__ 、__rdivmod__ 、 __rpow__
13增量赋值算术运算符
__iadd__ 、 __isub__ 、 __imul__ 、 __itruediv__ 、 __ifloordiv__ 、 __imod__ 、__ipow__
14位运算符
__invert__ ~ 、 __lshift__ << 、 __rshift__ >> 、 __and__ & 、 __or__ | 、 __xor__ ^
15反向位运算符
__rlshift__ 、 __rrshift__ 、 __rand__ 、 __rxor__ 、 __ror__
16增量赋值位运算符
__ilshift__ 、 __irshift__ 、 __iand__ 、 __ixor__ 、 __ior__
应用实例:
import math
from array import array
class Vector2d(object):
typecode = 'd'
def __init__(self, x, y):
self.__x = float(x) # 只有向量不可变,才能实现__hash__方法
self.__y = float(y)
@property
def x(self): # 可通过这两个方法读取公开特性,而不必访问私有属性
return self.__x
@property
def y(self):
return self.__y
def __repr__(self):
class_name = type(self).__name__
return '{}({!r},{!r})'.format(class_name, *self)
def __iter__(self):
return (i for i in (self.x, self.y))
def __str__(self):
return str(tuple(self))
def __bytes__(self):
return (bytes([ord(self.typecode)]) + bytes(array(self.typecode, self)))
def __eq__(self, other):
return tuple(self) == tuple(other)
def __abs__(self):
return math.hypot(self.x, self.y)
def __bool__(self):
return bool(abs(self))
# def __format__(self, format_spec=''):
# componets = (format(c, format_spec) for c in self)
# return '({},{})'.format(*componets)
def angle(self):
return math.atan2(self.x, self.y)
# 增强版,计算极坐标
def __format__(self, format_spec=''):
if format_spec.endswith('p'):
format_spec = format_spec[:-1]
coords = (abs(self), self.angle())
outer_fmt = '<{},{}>'
else:
coords = self
outer_fmt = '({},{})'
components = (format(c, format_spec) for c in coords)
return outer_fmt.format(*components)
def __hash__(self):
return hash(self.x) ^ hash(self.y)
def __complex__(self): # 实现虚数
return complex(self.x, self.y)
v1 = Vector2d(3, 4)
v2 = Vector2d(3.1, 4.2)
# print(format(v1))
# print(format(v1, '.2e'))
# print(format(v1, '.2f'))
# print(format(Vector2d(1, 1), 'p'))
# print(hash(v1)) # 不可hash的,想要变成可散列的,要把x和y变成不可改变的
# print(hash(v1))
# print(hash(v2))
# print(set([v1,v2]))
print(complex(v1))
print(complex(v2))