运算符重载
from math import hypot,sqrt
class Vector2D:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
"""
加法重载
:param other:
:return:
"""
x = self.x + other.x
y = self.y + other.y
return Vector2D(x, y)
def __str__(self):
return "Vector2D(x = {},y = {})".format(self.x, self.y)
def __sub__(self, other):
"""
减法重载
:param other:
:return:
"""
x = self.x - other.x
y = self.y - other.y
return Vector2D(x, y)
def __mul__(self, other):
"""
乘法重载
:param other:
:return:
"""
x = self.x * other.x
y = self.y * other.y
return Vector2D(x, y)
def __truediv__(self, other):
"""
除法重载
:param other:
:return:
"""
x = self.x / other.x
y = self.y / other.y
return Vector2D(x, y)
def __divmod__(self, other):
"""
返回商和余数的元组
:param other:
:return:
"""
pass
def __eq__(self, other):
"""
判断两个对象是否相等
:param other:
:return:
"""
pass
def __abs__(self):
"""
绝对值函数重载
:return:
"""
return sqrt(self.x ** 2 + self.y)
#或者return hypot(self.x, self.y) #效率更高,因为底层是拿C写的
def __len__(self):
"""
重写len方法,返回值必须为整数
:return:
"""
pass
def __iadd__(self, other):
"""
对+=重载,就地操作:对本身进行操作,如果不对此方法进行重写,+=时就会自动调用重写了的add方法
:param other:
:return:
"""
print("__iadd__")
return self.__add__(other)
v1 = Vector2D(1, 2)
v2 = Vector2D(4, 4)
print(v1 + v2)
print(v1 - v2)
print(v1 * v2)
print(v1 / v2)
v1 += v2
print(v1)
print(abs(v1))
ps:对方法重写后,可以返回NotImplemented,告诉编译器没有实现这个方法(尽管这个方法实际上实现了)
__add__、__radd__、__iadd__的区别
对于a+b:
- 如果a有__add__方法,并且返回值不是NotImplemented,则调用a的add方法
- 如果a没有add方法,或者返回了NotImplemented,检查b有没有radd方法,如果有,则执行,如果没有,则报错
- i表示就地操作,即+=,-=之类的
class A:
def __add__(self, other):
print("A__add")
return NotImplemented
def __radd__(self, other):
print("A__radd")
A() + B() #调用A的add方法
B() + A() #想调用B的add方法,但是没有被重写,于是调用A的radd方法
__repr__、__str__方法的区别
-
__str__
不存在的时候,会尝试调用repr -
__str__
是为了让人读,而repr是为了让机器读 -
__str__
是由print和str()函数调用,而__repr__
是由repr()函数调用
class Student:
def __init__(self, name):
self.name = name
def __repr__(self):
"""
如果没有实现__str__方法,则会调用此方法
:return:
"""
return "Student:%s"%self.name
s = Student("lisi")
print(s)
序列
只要实现了__getitem__
和__len__
方法,就会被认定是序列,就支持用for循环遍历,支持切片操作,等。
import collections
import random
#如果一个类里面只有属性,没有方法,则可以这么定义
Card = collections.namedtuple("Card", ["rank","suit"])
class Puke:
ranks = [str(n) for n in list(range(2,11)) + list("JQKA")] #后面的range和list连接起来了
suits = "黑桃 方块 梅花 红心".split()
def __init__(self):
self.cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self.cards)
def __getitem__(self, item):
return self.cards[item]
def __setitem__(self, key, value):
self.cards[key] = value
pk = Puke()
# print(pk.cards)
# print(len(pk.cards))
# for card in pk:
# print(card)
# pk[1:3] = Card(rank="A",suit="biubiubiu~"), Card(rank="A",suit="biubiubiu~")
# print(pk.cards)
#洗牌
random.shuffle(pk)
print(pk.cards)
print("\n发牌".center(50, "*"))
print(pk[:13])
print(pk[13:26])
print(pk[26:39])
print(pk[39:])
切片(slice(start, end, step))
slice:是用于规定序列的选取规则
step = slice(0,5,2)
component = [i for i in range(10)]
print(component[step])
网友评论