zoukankan      html  css  js  c++  java
  • 高级异常、运算符重载

    高级异常

    回顾异常相关的语句:

      try-except  用来捕获异常的通知

      try-finally  用来做一定要做的事

      reise    用来发生异常通知

      assert    用来根据条件来发出AssertionError类型的异常通知

    with语句

      语句: with 表达式1 [as 变量1],表达式2 [as 变量2]:

             语句块

      作用:使用于对资源进行访问的场合,确保使用过程中不管是否发生异常,都会执行必须的'清理'操作,并释放资源

      如:文件使用后自动关闭;线程中锁定的自动获取和释放等

     1 def read_from_file(filename='info.txt'):
     2     try:
     3         with open(filename) as f:
     4             print("正在读取文件")
     5             n = int(f.read())
     6             print('n=', n)
     7             print('文件已经关闭')
     8         # f = open(filename)
     9         # try:
    10         #     print("正在读取文件")
    11         #     n = int(f.read())
    12         #     print("n=", n)
    13         # finally:
    14         #     f.close()
    15         #     print("文件已经关闭")
    16     except OSError:
    17         print("文件打开失败")
    18 
    19 
    20 read_from_file()
    用with语句代替try-finally语句

    环境管理器

    1、类内有__enter____exit__实例方法的类被称为环境管理器

    2、能够用with语句管理的对象必须是环境管理器

    3、 __enter__方法将在进入with语句时被调用,并返回由as变量管理的对象

    4、__exit__将在离开with语句时被调用,且可以用参数来判断在离开with语句时是否有异常发生并做出相应的处理

     1 class A:
     2     def __enter__(self):
     3         print("已进入with语句")
     4         return self  # 返回的对象将由 as绑定
     5 
     6     def __exit__(self, exc_type, exc_val, exc_tb):
     7         print("已离开with语句")
     8 # a = A()
     9 with A() as a:
    10     print("这是with语句内的一条语句")
    11     int(input("请输入整数: "))
    环境管理器
    1 已进入with语句
    2 这是with语句内的一条语句
    3 请输入整数: 2
    4 已离开with语句
    结果

    对象的属性管理函数:

    1、getattr(obj, name[, default])从一个对象得到对象的属性;getattr(x, 'y') 等同于x.y;当属性不存在时,如果给出default参数,则返回default,如果没有给出default则产生一个AttributeError错误

    2、hasattr(obj, name)用给定的name返回对象obj是否有此属性,此种做法可以避免在getattr(obj, name)时引发错误

    3、setattr(obj, name, value)给对象obj的名为name的属性设置相应的值value, set(x,'y', v) 等同于 x.y = v

    4、delattr(obj, name)删除对象obj中的name属性,delattr(x, 'y') 等同于 del x.y

     1 class Car:
     2     def __init__(self, c, b):
     3         self.color, self.brand = c, b
     4 
     5     def get_car_attr(self, attr_name):
     6         '''此方法用于获取对象的属性,如果属性名attr_name
     7         在此对象内不存在则返回 None
     8         '''
     9         return getattr(self, attr_name, None)
    10 
    11 c1 = Car('黑色', 'Benz')
    12 v = c1.get_car_attr('color')
    13 # try:
    14 #     v = c1.__dict__['aaaaa']
    15 # except KeyError:
    16 #     v = None
    17 if v is None:
    18     print("没有颜色属性")
    19 else:
    20     print("颜色是:", v)
    getatter(obj,name[,default])

    运算符重载

      让自定义的类生成的对象(实例)能够使用运算符进行操作

    作用:让自定义的类的实例像内建对象一样能够运行运算符操作,让程序简单易读,对自定义的对象,将运算符赋予新的运算规则

    算术运算符的重载:

      __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)  右手边

     1 class MyNumber:
     2     def __init__(self, v):
     3         self.data = v
     4 
     5     def __repr__(self):
     6         return 'MyNumber(%d)' % self.data
     7 
     8     # def myadd(self, other):
     9     #     v = self.data + other.data
    10     #     return MyNumber(v)
    11 
    12     def __add__(self, other):
    13         print("__add__被调用")
    14         v = self.data + other.data
    15         return MyNumber(v)
    16 
    17     def __sub__(self, rhs):
    18         v = self.data - rhs.data
    19         return MyNumber(v)
    20 
    21 n1 = MyNumber(100)
    22 n2 = MyNumber(200)
    23 # n3 = n1.myadd(n2)
    24 # n3 = n1.__add__(n2)
    25 n3 = n1 + n2  # __add__被调用
    26 print(n3)   # MyNumber(300)
    27 n4 = n3 - n2
    28 print(n4)   # MyNumber(100)
    算术运算符重载
     1 class MyList:
     2     def __init__(self, iterable):
     3         self.data = list(iterable)
     4 
     5     def __add__(self, rhs):
     6         return MyList(self.data + rhs.data)
     7 
     8     def __repr__(self):
     9         return 'MyList(%r)' % self.data
    10 
    11     def __mul__(self, rhs):  # rhs 绑定整数
    12         return MyList(self.data * rhs)
    13 
    14 L1 = MyList([1, 2, 3])
    15 L2 = MyList([4, 5, 6])
    16 L3 = L1 + L2  # 等同于L1.__add__(L2)
    17 print(L3)  # MyList([1,2,3,4,5,6])
    18 L4 = L2 + L1  # 等同于L2.__add__(L1)
    19 print(L4)  # MyList([4,5,6,1,2,3])
    20 L5 = L1 * 2  # L1.__mul__(2)
    21 print(L5)  # MyList([1,2,3,1,2,3])
    算术运算符重载

    反向算术运算符的重载

      __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   冪

     1 class MyList:
     2     def __init__(self, iterable):
     3         self.data = list(iterable)
     4 
     5     def __add__(self, rhs):
     6         return MyList(self.data + rhs.data)
     7 
     8     def __repr__(self):
     9         return 'MyList(%r)' % self.data
    10 
    11     def __mul__(self, rhs):  # rhs 绑定整数
    12         print('__mul__被调用')
    13         return MyList(self.data * rhs)
    14     def __rmul__(self, lhs):
    15         print('__rmul__被调用')
    16         return MyList(self.data * lhs)
    17 
    18 L1 = MyList([1, 2, 3])
    19 L2 = MyList([4, 5, 6])
    20 L5 = L1 * 2  # L1.__mul__(2)
    21 print(L5)  # MyList([1,2,3,1,2,3])
    22 
    23 L6 = 2 * L1  # 2.__mul__(L1)
    24 print(L6)
    反向算术运算符重载

    复合赋值算术运算符的重载

      __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    冪

     1 class MyList:
     2     def __init__(self, iterable):
     3         print("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
     4         self.data = list(iterable)
     5 
     6     def __add__(self, rhs):
     7         print('__add__被调用')
     8         return MyList(self.data + rhs.data)
     9 
    10     def __repr__(self):
    11         return 'MyList(%r)' % self.data
    12 
    13     def __iadd__(self, rhs):
    14         print("__iadd__被调用!!!!")
    15         self.data.extend(rhs.data)
    16         return self
    17 
    18 L1 = MyList([1, 2, 3])  # aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    19 L2 = MyList([4, 5, 6])  # aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    20 L1 += L2  # 当没有__iadd__方法时,等同于调用L1 = L1 + L2    __iadd__被调用!!!!
    21 print(L1)   # MyList([1, 2, 3, 4, 5, 6])
    View Code

    比较运算符的重载

      __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

    位运算符重载

      __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   右移

    一元运算符的重载

    __neg__(self)   - self  负号
    __pos__(self)  + self    正号
    __invert__(self)  ~ self    取反

    一元运算符的重载方法:
      class 类名:
        def __xxx__(self):

     1 class MyList:
     2     def __init__(self, iterable):
     3         print("__init__被调用")
     4         self.data = list(iterable)
     5 
     6     def __repr__(self):
     7         return 'MyList(%r)' % self.data
     8 
     9     def __neg__(self):
    10         '''此方法用来制定 - self 返回的规则'''
    11         # L = [-x for x in self.data]
    12         L = (-x for x in self.data)
    13         return MyList(L)
    14 
    15 L1 = MyList([1, -2, 3, -4])
    16 L2 = -L1
    17 print(L2)
    View Code

    运算符重载说明:
      运算符重载不能改变运算符的优先级

    Python类名最好用驼峰命名法:
    MyList MyRange 大驼峰(所有单词首字母大写,其余小写)
    getStudentAge 小驼峰(第一个单词首字母小写,其它首字母大写)

    in / not in 运算符的重载

    重载方法:
      __contains__(self, e)   e in self  成员运算

     1 class MyList:
     2     def __init__(self, iterable):
     3         print("__init__被调用")
     4         self.data = list(iterable)
     5 
     6     def __repr__(self):
     7         return 'MyList(%r)' % self.data
     8 
     9     def __contains__(self, e):
    10         '''此方法用来实现 in / not in 运算符的重载'''
    11         print("__contains__被调用")
    12         for x in self.data:
    13             if x == e:
    14                 return True
    15         return False
    16 
    17 
    18 L1 = MyList([1, -2, 3, -4])
    19 if -2 in L1:
    20     print('-2 在 L1 中')
    21 else:
    22     print('-2 不在 L1中')
    23 
    24 
    25 # 当MyList的类内重载了__contains__方法,则not in也同时可用
    26 if -3 not in L1:
    27     print("-3 不在 L1中")
    28 else:
    29     print('-3 在 L2中')
    View Code

    索引和切片运算符的重载

      __getitem__(self, i)     x = self[i] 索引/切片取值
      __setitem__(self, i, v)      self[i] = v 索引/切片赋值
      __delitem__(self, i)        del self[i] del语句删除索引等

      作用:
      让自定义的类型的对象能够支持索引和切片操作

     1 class MyList:
     2     def __init__(self, iterable):
     3         print("__init__被调用")
     4         self.data = list(iterable)
     5 
     6     def __repr__(self):
     7         return 'MyList(%r)' % self.data
     8 
     9     def __getitem__(self, i):
    10         print("__getitem__被调用, i=", i)
    11         # if type(i) is not int:
    12         #     raise TypeError
    13         return self.data[i]
    14 
    15     def __setitem__(self, i, v):
    16         print("__setitem__被调用, i=", i, 'v =', v)
    17         self.data[i] = v  # 修改data绑定的列表
    18 
    19 
    20 L1 = MyList([1, -2, 3, -4])
    21 v = L1[-1]
    22 print(v)
    23 
    24 L1[1] = 2  # 等同于调用 L1.__setitem__(1, 2)
    25 print(L1)
    26 
    27 # 以下操作会出错
    28 # print(L1[100000000000])
    29 # print(L1['hello'])
    View Code

    slice 构造函数

    作用: 用于创建一个Slice切片对象, 此对象存储一个切片的起始值,终止值和步长信息
      slice(start, stop=None, step=None) 创建一个切片对象
    slice的对象的属性:
      s.start 切片起始值,默认为None
      s.stop 切片终止值,默认为None
      s.step 切片步长 ,默认为None

     1 class MyList:
     2     def __init__(self, iterable):
     3         print("__init__被调用")
     4         self.data = list(iterable)
     5 
     6     def __repr__(self):
     7         return 'MyList(%r)' % self.data
     8 
     9     def __getitem__(self, i):
    10         print("__getitem__被调用, i=", i)
    11         if type(i) is int:
    12             print("正在做索引操作")
    13         elif type(i) is slice:
    14             print("正在做切片操作")
    15             print("切片的起始值:", i.start)
    16             print("切片的终止值:", i.stop)
    17             print("切片的步长:", i.step)
    18         else:
    19             raise KeyError
    20         return self.data[i]
    21 
    22 
    23 L1 = MyList([1, -2, 3, -4, 5, -6])
    24 
    25 print(L1[::2])  # 等同于调用L1[slice(None, None, 2)]
    View Code
  • 相关阅读:
    高效 告别996,开启java高效编程之门 5-4新集合类型MultiSet
    高效 告别996,开启java高效编程之门 5-3不可变集合
    高效 告别996,开启java高效编程之门 5-2实战Optional使用
    高效 告别996,开启java高效编程之门 5-1Guava开场
    高效 告别996,开启java高效编程之门 4-6本节总结
    高效 告别996,开启java高效编程之门 4-5TWR进阶与特殊情况
    高效 告别996,开启java高效编程之门 4-4TWR方式关闭流资源
    高效 告别996,开启java高效编程之门 4-3传统方式关闭流资源
    省市经纬度
    Web移动端常见问题-摘抄
  • 原文地址:https://www.cnblogs.com/LXP-Never/p/9385213.html
Copyright © 2011-2022 走看看