(D20)Python-异常高级,运算符重载

版权声明:转载请声明 https://blog.csdn.net/dirckes8813/article/details/83616235

异常(高级)

异常相关的语句:

  • try-except
  • try-finally
  • raise 触发异常,发生错误通知
  • assert 根据条件触发AssertionError类型的错误通知

with 语句

with语句

  • 语法:
    • with 表达式1[as 变量1], 表达式2 [as 变量2], …:
      • 语句块
  • 作用:
    • 使用于对资源进行访问的场合,确保使用过程中不管是否发生异常,都会执行必须的’清理’操作,并释放资源
    • 如: 文件使用后自动关闭,线程中锁的自动获取和释放等
  • 说明:
    • 执行表达式用as子句中的变量绑定生成的对象
    • 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, '失败')

示例

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 幂运算

扫描二维码关注公众号,回复: 4420208 查看本文章

示例

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内’)

猜你喜欢

转载自blog.csdn.net/dirckes8813/article/details/83616235
今日推荐