函数重写
在自定义类内添加相应的方法,让自定义类创建的实例能像内建对象一样进行内建函数操作
对象转字符串函数:
repr(obj) 返回一个能代表此对象的表达式字符串,通常
eval(repr(obj)) == obj (这个字符串通常是给python解释执行器运行用的)str(obj) 通过给定的对象返回一个字符串(这个字符串通常是给人阅读的)
对象转字符串函数的重写方法:
repr(obj) 函数的重写方法:
def __repr__(self):str(obj) 函数的重写方法:
def __str__(self):说明:
1. str(obj) 函数先查找, obj.__str__()方法,调用此方法并返回结果
2. 如果没有obj.__str__()方法时,则返回obj.__repr__()方法的结果并返回
3. 如果obj.__repr__方法不存在,则调用object类的__repr__实例方法显示<__main__.XXXX object at 0xAABBCCDD>格式的字符串示例:
# 此示例示意通过重写 repr 和 str方法改变转为字符串的规则 class MyNumber: def __init__(self, value): '构造函数,初始化MyNumber对象' self.data = value def __str__(self): '''转换为普通人识别的字符串''' # print("__str__方法被调用!") return "自定义数字类型对象: %d" % self.data def __repr__(self): '''转换为eval能够识别的字符串''' return 'MyNumber(%d)' % self.data n1 = MyNumber(100) n2 = MyNumber(200) print('repr(n1) ====>', repr(n1)) print('str(n2) ====>', str(n2))
其它内建函数的重写方法:
__abs__ abs(obj) 函数
__len__ len(obj) 函数(必须返回整数)
__reversed__ reversed(obj) 函数(必须返回可迭代对象
__round__ round(obj) 函数示例:
# 此示例示意abs 函数的重写 class MyInteger: def __init__(self, v): self.data = v def __repr__(self): return 'MyInteger(%d)' % self.data def __abs__(self): v = abs(self.data) return MyInteger(v) # 用v创建另一个MyInteger对象 def __len__(self): return 10000 I1 = MyInteger(-10) print('I1 =', I1) I2 = abs(I1) print("I2 =", I2) print('len(I2)=', len(I2)) # 10000
数值转换函数的重写:
__complex__ complex(obj) 函数
__int__ int(obj) 函数
__float__ float(obj) 函数
__bool__ bool(obj) 函数 (见下面布尔测试函数重载)示例:
# 此示例示意数据转换构造函数的重写方法 class MyNumber: def __init__(self, value): self.data = value def __repr__(self): return 'MyNumber(%d)' % self.data def __int__(self): 'int函数的重载' return self.data n1 = MyNumber(100) x = int(n1) print(n1) print(bool(n1)) # True n2 = MyNumber(0) print(bool(n2)) # True
布尔测试函数重写:
格式:
__bool__
作用:
用于bool(obj) 函数取值
用于if语句的真值表达式中
用于while 语句的真值表达式中
说明:
1. 当自定义的类内有 __bool__(self) 方法时,以此方法的返回值作为bool(obj) 的返回值
2. 当不存在__bool__(self) 方法时,bool(x) 返回__len__(self) 方法的返回值是否为零来测试布尔值
3. 当不存在__len__(self) 方法时,则直接返回True示例:
# 此示例示意bool(x) 函数的重写 class MyList: '自定义类型的列表,用来保存数据,内部用一个列表来存储数据' def __init__(self, iterable=()): self.data = [x for x in iterable] def __repr__(self): return 'MyList(%s)' % self.data def __len__(self): '''返回长度''' print("__len__方法被调用") return len(self.data) def __bool__(self): print("__bool__方法调用") for x in self.data: if not x: return False return True # return False # <<=== 所有对象都为False myl = MyList([0, -1, 2, -3]) # myl = MyList() print(myl) print(bool(myl)) if myl: print("myl为真值") else: print('myl为假值')
迭代器(高级):
什么是迭代器
可以通过next(it)函数取值的对象就是迭代器迭代器协议
迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定迭代器协议实现方法:
__next__(self) 方法来实现迭代器协议语法形式:
class MyIterator:
def __next__(self):
迭代器协议
return 数据
什么是可迭代对象:
是指能用iter(obj) 函数返回迭代器的对象(实例)
可迭代对象内部需要定义__iter__(self) 方法来返回迭代器对象
对象的属性管理函数:
getattr(obj, name[,default]) 从一个对象得到对象的属性;getattr(x,'y') 等同于x.y,当属性不存在时,如果给出default参数则返回defualt, 如果没有给出default,则产生一个AttributeError错误
hasattr(obj, name) 用给定的name返回对象obj是否有此属性,此种做法可以避免在getattr(obj,name) 时引发错误
setattr(obj, name, value) 给对象obj的名为name的属性设置相应的值value; set(x, 'y', z) 等同于 x.y = z
delattr(obj, name) 删除对象obj中的name属性,delattr(x, 'y') 等同于 del x.y
hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
需要注意的是name要用括号括起来1 >>> class test(): 2 ... name="xiaohua" 3 ... def run(self): 4 ... return "HelloWord" 5 ... 6 >>> t=test() 7 >>> hasattr(t, "name") #判断对象有name属性 8 True 9 >>> hasattr(t, "run") #判断对象有run方法 10 True
getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号。1 >>> class test(): 2 ... name="xiaohua" 3 ... def run(self): 4 ... return "HelloWord" 5 ... 6 >>> t=test() 7 >>> getattr(t, "name") #获取name属性,存在就打印出来。 8 'xiaohua' 9 >>> getattr(t, "run") #获取run方法,存在就打印出方法的内存地址。 10 <bound method test.run of <__main__.test instance at 0x0269C878>> 11 >>> getattr(t, "run")() #获取run方法,后面加括号可以将这个方法运行。 12 'HelloWord' 13 >>> getattr(t, "age") #获取一个不存在的属性。 14 Traceback (most recent call last): 15 File "<stdin>", line 1, in <module> 16 AttributeError: test instance has no attribute 'age' 17 >>> getattr(t, "age","18") #若属性不存在,返回一个默认值。 18 '18'
setattr(object, name, values)
给对象的属性赋值,若属性不存在,先创建再赋值。1 >>> class test(): 2 ... name="xiaohua" 3 ... def run(self): 4 ... return "HelloWord" 5 ... 6 >>> t=test() 7 >>> hasattr(t, "age") #判断属性是否存在 8 False 9 >>> setattr(t, "age", "18") #为属相赋值,并没有返回值 10 >>> hasattr(t, "age") #属性存在了 11 True
异常(高级)
可以用于异常的语句:
try-except # 捕获异常,得到异常通知
try-finally # 做任何流程(正常流程/异常流程)都必须要执行的语句
raise # 发送异常通知
assert # 根据条件发送异常通知with 语句
语法:
with 表达式1 [as 变量1], 表达式2 [as 变量2], ...:
语句块
作用:
使用于对资源进行访问的场合,确保使用过程中不管是否发生异常都会执行必要的'清理操作',并释放资源
(如:文件使用后自动关闭,线程中锁的自动获取和释放等)
说明:
执行表达式 as子句中的变量绑定生成的对象
with语句并不改变异常的状态示例:
# 此示例示意用with语句打开文件和自动关闭文件的操作 # try: # f = open('a.txt') # try: # for x in f: # print(x) # int('abc') # 出错异常 # finally: # f.close() # except OSError: # print("打开文件失败") # except ValueError: # print('操作文件过程中失败') try: with open('a.txt') as f: for x in f: print(x) int("abc") # 出现异常 except OSError: print("打开文件失败") except ValueError: print('操作文件过程中失败')
环境管理器
类内有__enter__ 和 __exit__实例方法的类被称为环境管理器
能够用with进行管理的对象必须是环境管理器说明:
__enter__将在进入with语句时被调用并返回由as变量绑定的对象
__exit__将在离开with语句时被调用,且可以用参数来判断在离开with语句时是否有异常发生并做出相应的处理with语句的实际工作流程:
1. 计算expression表达式,所得到的对象就称为环境管理器,它必须有__enter__和__exit__方法。
2. 环境管理器的__enter__会首先被调用,如果存在as语句,它的返回值会赋给as后面的变量,否则直接丢弃。
3. with_block中的代码块会执行。
4. 最后执行__exit__(type, value, traceback)方法。
- 如果with语句引发了异常,且该方法的返回值是假,那么异常就会被重新引发,否则异常会终止。正常情况下我们希望异常被重新引发,这样才能讲异常 传递到with代码块外面去,便于发现和处理。
- 如果with语句没有引发异常,其中type, value, traceback参数都会以None值传递。示例:
# 此示例示意 让一个自定义的类创建的对象能够使用with语句 class A: '''此类的对象可用于with语句进行管''' def __enter__(self): print("已经进入with语句,资源分配成功!") return self # <<<--此处返回的对象将由 as 变量绑定 def __exit__(self, exc_type, exc_val, exc_tb): print("已经离开with语句,资源释放成功!") if exc_type is None: print("当离开with语句时没有发生异常") else: print('有异常发生,异常类型是:', exc_type, '异常值是:', exc_val) with A() as a: print("这是with中的语句") raise ValueError("故意制造的异常")
运算符重载
什么是运算符重载
让自定义的类生成的对象(实例)能够使用运算符进行操作作用:
1. 让自定义的类的实例能够运行运算符操作
2. 让程序简洁易读
3. 对自定义对象将运算符赋序新的运算规则
说明:
运算符重载方法的参数已经有固定的含义,不建议改变原有的意义
算术运算符重载
方法名 运算符和表达式 说明
__add__(self, rhs) self + rhs 加法
__sub__(self, rhs) self - rhs 减法
__mul__(self, rhs) self * rhs 乘法
__truediv__(self, rhs) self / rhs 除法
__floordiv__(self, rhs) self // rhs 地板除
__mod__(self, rhs) self % rhs 取模(求余)
__pow__(self, rhs) self ** rhs 幂rhs(right hand side) 右手边
反向算术运算符的重载
当运算符的左侧为内建类型,右侧为自义类型的对象进行算术运算符运算时,会出现TypeError错误,
因无法修改内建类的代码来实现运算符重载,此时需要使用反向算术运算符重载方法名 运算符和表达式 说明
__radd__(self, lhs) lhs + self 加法
__rsub__(self, lhs) lhs - self 减法
__rmul__(self, lhs) lhs * self 乘法
__rtruediv__(self, lhs) lhs / self 除法
__rfloordiv__(self, lhs) lhs // self 地板除
__rmod__(self, lhs) lhs % self 取模(求余)
__rpow__(self, lhs) lhs ** self 幂lhs(left hand side) 左手边
复合赋值算术运算符的重载
以复合赋值算术运算符 x += y 为例,此运算会优先调用x.__iadd__(y) 方法,
如果没有__iadd__方法时会将复合赋值运算拆解为 x = x + y,然后调用x = x.__add__(y) 方法
如果再不存在 __add__方法则会触发TypeError异常方法名 运算符和表达式 说明
__iadd__(self, lhs) lhs += self 加法
__isub__(self, lhs) lhs -= self 减法
__imul__(self, lhs) lhs *= self 乘法
__itruediv__(self, lhs) lhs /= self 除法
__ifloordiv__(self, lhs) lhs //= self 地板除
__imod__(self, lhs) lhs %= self 取模(求余)
__ipow__(self, lhs) lhs **= self 幂
比较运算符的重载
方法名 运算符和表达式 说明
__lt__(self, rhs) self < rhs 小于
__le__(self, rhs) self <= rhs 小于等于
__gt__(self, rhs) self > rhs 大于
__ge__(self, rhs) self >= rhs 大于等于
__eq__(self, rhs) self == rhs 等于
__ne__(self, rhs) self != rhs 不等于
位运算符重载
方法名 运算符和表达式 说明
__invert__(self) ~ self 取反(一元运算符)
__and__(self, rhs) self & rhs 位与
__or__(self, rhs) self | rhs 位或
__xor__(self, rhs) self ^ rhs 位异或
__lshift__(self, rhs) self << rhs 左移
__rshift__(self, rhs) self >> rhs 右移
反向位运算符重载
方法名 运算符和表达式 说明
__rand__(self, lhs) lhs & self 位与
__ror__(self, lhs) lhs | self 位或
__rxor__(self, lhs) lhs ^ self 位异或
__rlshift__(self, lhs) lhs << self 左移
__rrshift__(self, lhs) lhs >> self 右移
复合赋值位运算符重载
方法名 运算符和表达式 说明
__iand__(self, rhs) self &= rhs 位与
__ior__(self, rhs) self |= rhs 位或
__ixor__(self, rhs) self ^= rhs 位异或
__ilshift__(self, rhs) self <<= rhs 左移
__irshift__(self, rhs) self >>= rhs 右移
一元运算符重载
方法名 运算符和表达式 说明
__invert__(self) ~ self 取反(一元运算符)
__pos__(self) + self 正号
__neg__(self) - self 负号
in / not in 运算符重载
重载方法:
def __contains__(self, e):
....
索引和切片运算符的重载
方法名 运算符和表达式 说明
__getitem__(self, i) x = self[i] 索引/切片取值
__setitem__(self, i, val) self[i] = val 索引/切片赋值
__delitem__(self, i) del self[i] 删除索引/切片作用:
让自定义的类的对象能够支持索引和切片操作
slice 函数:
作用:
用于创建一个slice切片对象,此对象存储切片的信息
格式:
slice(start=None, stop=None, step=None)
slice对象的属性
s.start 切片的起始值, 默认为None
s.stop 切片的终止值, 默认为None
s.step 切片的步长, 默认为None
特性属性 @property
实现其它语言所拥有的 getter(读) 和 setter(写) 的功能
作用:
Python内置的
@property
装饰器就是负责把一个方法变成属性调用的
用来模拟一个属性
通过@property 装饰器可以对模拟属性的取值和赋值加以控制
@property可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/deleter也是需要的。
1、只有@property表示只读。
2、同时有@property和@*.setter表示可读可写。3、同时有@property和@*.setter和@*.deleter表示可读可写可删除。
示例:
class Student: def __init__(self, s): self.__score = s # 私有属性,不让其它人任意修改成绩 @property def score(self): '''取值实现getter方法''' print('正在取值') return self.__score @score.setter def score(self, v): '''实现设置者setter,对用户的赋值加以限制''' assert 0 <= v <= 100, '成绩不合法' self.__score = v s = Student(59) print(s.score) # 希望有一个属能得到成绩 s.score = 80 # 通过s.score 来修改成功 print(s.score) # 80 try: s.score = 102 print(s.score) except Exception as err: print(err) # 成绩不合法