目录
对象属性管理函数:
详见:内建函数.html
getattr(dog1,'color',没有此属性)
hasattr(dog1,'kinds')
delatter = del
异常(高级)
异常相关的语句:
try-except
try-finally
raise 触发异常,发生错误通知
assert 根据条件触发AssertionError类型的错误通知
with 语句
with语句
语法:
with 表达式1[as 变量1], 表达式2 [as 变量2], ...:
语句块
作用:
使用于对资源进行访问的场合,确保使用过程中不管是否发生异常,都会执行必须的'清理'操作,并释放资源
如: 文件使用后自动关闭,线程中锁的自动获取和释放等
说明:
执行表达式用as子句中的变量绑定生成的对象
with 语句并不改变异常的的状态
# 此示例示意with语句的用法
src_file = input("请输入源文件: ")
try:
src = open(src_file, 'rb')
try:
try:
# 准备打开别一个文件
dst_file = input("请输入目标文件: ")
dst = open(dst_file, 'wb')
try:
# 开始读写文件
b = src.read()
dst.write(b)
finally:
# 关闭文件
dst.close()
except OSError:
print('打开写文件失败')
finally:
src.close()
except OSError:
print("打开文件", src_file, '失败')
# 此示例示意with语句的用法
src_file = input("请输入源文件: ")
dst_file = input("请输入目标文件: ")
try:
with open(src_file, 'rb') as src:
# 准备打开别一个文件
with open(dst_file, 'wb') as dst:
# 开始读写文件
b = src.read()
dst.write(b)
except OSError:
print("复制失败")
src_file = input("请输入源文件: ")
dst_file = input("请输入目标文件: ")
try:
with open(src_file, 'rb') as src, \
open(dst_file, 'wb') as dst:
b = src.read()
dst.write(b)
except OSError:
print("复制失败")
环境管理器(也有叫上下文管理器)
1.类内有__enter__方法和__exit__实例方法的类被称为环境管理器
2.能够用with语句进行管理的对象必须是环境管理器
3.__enter__将在进入with语句时被调用,并返回由 as 变量绑定的对象
4.__exit__将在离开with语句时被调用,且可以用参数来判断在离开with语句时是否有异常发生并做出相应的处理
# 此示例示意环境管理器类的定义的使用
class A:
'''此类的对象可以用于with语句进行管理'''
def __enter__(self):
print("已经进入with语句")
return self
def __exit__(self, exc_type, exc_value, exc_tb):
print("已经离开了with语句")
if exc_type is None:
print("在with语句内部没有发生异常,正常离开with")
else:
print("离开with语句时出现异常")
print("异常类型是:", exc_type)
print("错误的值是:", exc_value)
try:
with A() as a:
print("这是with语句里打印的")
3 / 0 # 触发异常
except:
print("有异常发生,程序已转为正常!")
print("程序退出")
运算符重载
什么是运算符重载:
让自定义的类生成的对象(实例)能够实例运算符进行操作
作用:
让自定义类的实例像内建对象一样进行运算符操作
让程序简洁易读
对自定义的对象将运算符赋予新的运算规则
说明:
运算符重载方法的参数已经有固定的含义,不建议改变原有的意义
算术运算重载
方法名 运算符和表达式 说明
__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 hands side)
# 此示例示意自定义的类通过运算符重载实现运算符操作
class MyNumber:
def __init__(self, v):
self.data = v
def __repr__(self):
return "MyNumber(%d)" % self.data
def __add__(self, other):
'''实现加法操作,生成一个新的对象并返回给调用者'''
print("__add__方法被调用")
return MyNumber(self.data + other.data)
def __sub__(self, rhs):
return MyNumber(self.data - rhs.data)
n1 = MyNumber(100)
n2 = MyNumber(200)
n3 = n1 + n2 # 等同于n1.__add__(n2)
# n3 = n1.__add__(n2)
print(n1, "+", n2, '=', n3) # MyNumber(300) ???
n4 = n1 - n2
print('n4 =', n4)
二元运算符的重载方法格式:
def __xxx__(self,other):
运算规则的语句...
反向算术运算符的重载
当运算符的左侧为内建类型时,右侧为自定义类型进行算术运算时,会出现TypeError错误,
因无法修改内建类型的代码来实现运算符重载,此时需要使用反向运算符重载来完成重载
反向算术运算重载
方法名 运算符和表达式 说明
__radd__(self,rhs) rhs + self 加法
__rsub__(self,rhs) rhs - self 减法
__rmul__(self,rhs) rhs * self 乘法
__rtruediv__(self,rhs) rhs / self 除法
__rfloordiv__(self,rhs) rhs // self 地板法
__rmod__(self,rhs) rhs % self 求余(取模)
__rpow__(self,rhs) rhs ** self 幂运算
# 此示例示意反向算术运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __mul__(self, rhs):
print("__mul__")
return MyList(self.data * rhs)
def __rmul__(self, lhs):
print("__rmul__被调用")
return MyList(self.data * lhs)
L1 = MyList([1, 2, 3])
L6 = 2 * L1 # 等同于2.__add__(L1) 或 L1.__rmul__(2)
print(L6)
复合赋值算术运算符重载
以复合赋值算术运算符为例x += y 为例,此运算符会优先调用x.__iadd__(y) 方法,
如果没有__iadd__方法时会将复合赋值运算符拆为x = x + y,然后调用x = x.__add__(y) 方法
其它复合赋值算术运算符也具有相同的规则
复合算术运算重载
方法名 运算符和表达式 说明
__iadd__(self,rhs) self += rhs 加法
__isub__(self,rhs) self -= rhs 减法
__imul__(self,rhs) self *= rhs 乘法
__itruediv__(self,rhs) self /= rhs 除法
__ifloordiv__(self,rhs) self //= rhs 地板法
__imod__(self,rhs) self %= rhs 求余(取模)
__ipow__(self,rhs) self **= rhs 幂运算
比较运算符的重载
方法名 运算符和表达式 说明
__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 不等于
注:比较运算符通常返回布尔值True 或False
# 此示例示意比较运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __gt__(self,rhs):
'''只比较第一个元素'''
print("__gt__被调用")
return self.data > rhs.data
def __eq__(self, rhs):
print('__eq__被调用')
return self.data == rhs.data
L1 = MyList([1, 2, 3])
L2 = MyList([1, 2, 3])
print(L1, '>', L2, '=', L1 > L2)
print(L1, '<', L2, '=', L1 < L2)
print(L1, '==', L2, 'is', L1 == L2)
print(L1, '!=', L2, 'is', L1 != L2)
位运算符的重载
方法名 运算符和表达式 说明
__invert__(self,rhs) ~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, rhs) lhs & self 位与
__ror__(self, rhs) lhs | self 位或
__rxor__(self, rhs) lhs ^ self 位异或
__rlshift__(self, rhs) lhs << self 左移
__rrshift__(self, rhs) 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 右移
一元运算符的重载
方法名 运算符和表达式 说明
__neg__(self) - self 负号
__pos__(self) + self 正号
__invert__(self) ~ self 取反
语法格式:
def __xxx__(self):
...示例:
# 此示例示意一元运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __neg__(self):
'''规则是正变负,负变正'''
# L = [-x for x in self.data]
L = (-x for x in self.data)
return MyList(L)
L1 = MyList([1, -2, 3, -4, 5])
L2 = -L1 # 等同于L1.__neg__()
print(L2)
in / not in 运算符
__contains__(self, e) e in self 成员运算
索引和切片运算符的重载
[]
重载方法 运算符和表达式 说明
__getitem__(self, i) x = self[i] 索引/切片取值
__setitem__(self,i,val) self.[i]=val 索引/切片赋值
__delitem__(self, i) del self[i] del语句索引/切片
作用:
让自定义的类型的对象能够支持索引和切片操作
# 此示例示意[]运算符的重载
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr__(self):
return 'MyList(%r)' % self.data
def __getitem__(self, i):
print("i =", i)
return self.data[i]
def __setitem__(self, i, val):
self.data[i] = val
L1 = MyList([1, -2, 3, -4, 5])
x = L1[0] # L1.__getitem__(0)
print(x)
L1[1] = 2 # L1.__setitem__(1, 2)
print(L1)
slice 构造函数
作用:
用于创建一个slice切片对象, 此对象存储一个切片起始值,终止值, 步长值信息
格式:
slice(start=None, stop=None, step=None) 创建 一个slice 切片对象
slice 对象属性
s.start 切片的起始值
s.stop 切片的终止值
s.step 要片的步长
特性属性 @property
实现其它语言所拥有的 getter 和 setter功能
作用:
用来模拟一个属性
通过@property装饰器可以对模拟的属性赋值和取值加以控制
# 此示例示意特性属性的用法
class Student:
def __init__(self, score):
self.__score = score
def get_score(self):
'''实现getter'''
return self.__score
def set_score(self, s):
'''实现setter'''
print("正在调用setter")
if 0 <= s <= 100:
self.__score = s
else:
raise ValueError
score = property(get_score, set_score)
s = Student(59)
print(s.score) # print(s.get_score())
s.score = 97 # s.set_score(97)
print(s.score) # ...
练习:
实现有序集合类 OrderSet 能实现两个集合的
交集 & 全集 | 补集 - 对称补集 ^ == / !=
in / not in 等集合操作
要求内部用list 存储
class OrderSet:
...
s1 = OrderSet([1, 2, 3, 4])
s2 = OrderSet([3, 4, 5])
print(s1 & s2) # OrderSet([3, 4])
print(s1 | s2) # OrderSet([1, 2, 3, 4, 5])
print(s1 ^ s2) # OrderSet([1, 2, 5])
if OrderSet([1,2,3]) != OrderSet([1, 2, 3, 4]):
print("不相等")
if s2 == OrderSet([3,4,5]):
print('s2 等于 OrderSet([3,4,5])')
if 2 in s1:
print('2 在s1内')