解析python高级异常和运算符重载

作者:凌逆战 时间:2021-06-17 00:56:41 

一、高级异常

回顾异常相关的语句:

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

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

reise:用来发生异常通知

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

with语句:

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

         语句块

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

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

用with语句代替try-finally语句


def read_from_file(filename='info.txt'):
    try:
        with open(filename) as f:
            print("正在读取文件")
            n = int(f.read())
            print('n=', n)
            print('文件已经关闭')
        # f = open(filename)
        # try:
        #     print("正在读取文件")
        #     n = int(f.read())
        #     print("n=", n)
        # finally:
        #     f.close()
        #     print("文件已经关闭")
    except OSError:
        print("文件打开失败")

read_from_file()

二、环境管理器

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

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

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

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


class A:
    def __enter__(self):
        print("已进入with语句")
        return self  # 返回的对象将由 as绑定

def __exit__(self, exc_type, exc_val, exc_tb):
        print("已离开with语句")
# a = A()
with A() as a:
    print("这是with语句内的一条语句")
    int(input("请输入整数: "))

已进入with语句

这是with语句内的一条语句

请输入整数: 2

2.1、对象的属性管理函数

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


class Car:
    def __init__(self, c, b):
        self.color, self.brand = c, b

def get_car_attr(self, attr_name):
        '''此方法用于获取对象的属性,如果属性名attr_name
        在此对象内不存在则返回 None
        '''
        return getattr(self, attr_name, None)

c1 = Car('黑色', 'Benz')
v = c1.get_car_attr('color')
# try:
#     v = c1.__dict__['aaaaa']
# except KeyError:
#     v = None
if v is None:
    print("没有颜色属性")
else:
    print("颜色是:", v)

getatter(obj,name[,default])

三、运算符重载

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

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

3.1、算术运算符的重载

__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 myadd(self, other):
    #     v = self.data + other.data
    #     return MyNumber(v)

def __add__(self, other):
       print("__add__被调用")
        v = self.data + other.data
        return MyNumber(v)

def __sub__(self, rhs):
        v = self.data - rhs.data
        return MyNumber(v)

n1 = MyNumber(100)
n2 = MyNumber(200)
# n3 = n1.myadd(n2)
# n3 = n1.__add__(n2)
n3 = n1 + n2  # __add__被调用
print(n3)   # MyNumber(300)
n4 = n3 - n2
print(n4)   # MyNumber(100)

class MyList:
    def __init__(self, iterable):
        self.data = list(iterable)

def __add__(self, rhs):
        return MyList(self.data + rhs.data)

def __repr__(self):
        return 'MyList(%r)' % self.data

def __mul__(self, rhs):  # rhs 绑定整数
        return MyList(self.data * rhs)

L1 = MyList([1, 2, 3])
L2 = MyList([4, 5, 6])
L3 = L1 + L2  # 等同于L1.__add__(L2)
print(L3)  # MyList([1,2,3,4,5,6])
L4 = L2 + L1  # 等同于L2.__add__(L1)
print(L4)  # MyList([4,5,6,1,2,3])
L5 = L1 * 2  # L1.__mul__(2)
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 冪


class MyList:
    def __init__(self, iterable):
        self.data = list(iterable)

def __add__(self, rhs):
        return MyList(self.data + rhs.data)

def __repr__(self):
       return 'MyList(%r)' % self.data

def __mul__(self, rhs):  # rhs 绑定整数
        print('__mul__被调用')
        return MyList(self.data * rhs)
    def __rmul__(self, lhs):
        print('__rmul__被调用')
        return MyList(self.data * lhs)

L1 = MyList([1, 2, 3])
L2 = MyList([4, 5, 6])
L5 = L1 * 2  # L1.__mul__(2)
print(L5)  # MyList([1,2,3,1,2,3])

L6 = 2 * L1  # 2.__mul__(L1)
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  冪


class MyList:
   def __init__(self, iterable):
       print("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
       self.data = list(iterable)

def __add__(self, rhs):
       print('__add__被调用')
       return MyList(self.data + rhs.data)

def __repr__(self):
       return 'MyList(%r)' % self.data

def __iadd__(self, rhs):
       print("__iadd__被调用!!!!")
       self.data.extend(rhs.data)
       return self

L1 = MyList([1, 2, 3])  # aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L2 = MyList([4, 5, 6])  # aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L1 += L2  # 当没有__iadd__方法时,等同于调用L1 = L1 + L2    __iadd__被调用!!!!
print(L1)   # MyList([1, 2, 3, 4, 5, 6])

六、比较运算符的重载

__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):


class MyList:
   def __init__(self, iterable):
       print("__init__被调用")
       self.data = list(iterable)

def __repr__(self):
       return 'MyList(%r)' % self.data

def __neg__(self):
       '''此方法用来制定 - self 返回的规则'''
       # L = [-x for x in self.data]
       L = (-x for x in self.data)
       return MyList(L)

L1 = MyList([1, -2, 3, -4])
L2 = -L1
print(L2)

运算符重载说明:

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

Python类名最好用驼峰命名法:

  • MyList  MyRange  大驼峰(所有单词首字母大写,其余小写)

  • getStudentAge    小驼峰(第一个单词首字母小写,其它首字母大写)

十一、in / not in 运算符的重载

重载方法:

__contains__(self, e) e in self 成员运算


class MyList:
   def __init__(self, iterable):
       print("__init__被调用")
       self.data = list(iterable)

def __repr__(self):
       return 'MyList(%r)' % self.data

def __contains__(self, e):
       '''此方法用来实现 in/ not in 运算符的重载'''
       print("__contains__被调用")
       for x in self.data:
           if x == e:
               return True
       return False

L1 = MyList([1, -2, 3, -4])
if -2 in L1:
   print('-2 在 L1 中')
else:
   print('-2 不在 L1中')

# 当MyList的类内重载了__contains__方法,则not in也同时可用
if -3 not in L1:
   print("-3 不在 L1中")
else:
   print('-3 在 L2中')

十二、索引和切片运算符的重载

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

作用:

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


class MyList:
   def __init__(self, iterable):
       print("__init__被调用")
       self.data = list(iterable)

def __repr__(self):
       return 'MyList(%r)' % self.data

def __getitem__(self, i):
       print("__getitem__被调用, i=", i)
       # if type(i) is not int:
       #     raise TypeError
       return self.data[i]

def __setitem__(self, i, v):
       print("__setitem__被调用, i=", i, 'v =', v)
       self.data[i] = v  # 修改data绑定的列表

L1 = MyList([1, -2, 3, -4])
v = L1[-1]
print(v)

L1[1] = 2  # 等同于调用 L1.__setitem__(1, 2)
print(L1)

# 以下操作会出错
# print(L1[100000000000])
# print(L1['hello'])

十三、slice 构造函数

作用:用于创建一个Slice切片对象, 此对象存储一个切片的起始值,终止值和步长信息

slice(start, stop=None, step=None)  创建一个切片对象

slice的对象的属性:

  • s.start  切片起始值,默认为None

  • s.stop   切片终止值,默认为None

  • s.step   切片步长  ,默认为None


class MyList:
   def __init__(self, iterable):
       print("__init__被调用")
       self.data = list(iterable)

def __repr__(self):
       return 'MyList(%r)' % self.data

def __getitem__(self, i):
       print("__getitem__被调用, i=", i)
       if type(i) is int:
           print("正在做索引操作")
       elif type(i) is slice:
           print("正在做切片操作")
           print("切片的起始值:", i.start)
           print("切片的终止值:", i.stop)
           print("切片的步长:", i.step)
       else:
           raise KeyError
       return self.data[i]

L1 = MyList([1, -2, 3, -4, 5, -6])

print(L1[::2])  # 等同于调用L1[slice(None, None, 2)]

来源:https://www.cnblogs.com/LXP-Never/p/9385213.html

标签:python,异常,运算符重载
0
投稿

猜你喜欢

  • python代码的几种常见加密方式分享

    2021-05-19 02:14:56
  • Jquery AJAX POST与GET之间的区别

    2024-04-29 13:58:32
  • python3实现的zip格式压缩文件夹操作示例

    2023-07-31 18:17:48
  • sqlserver 2000中创建用户的图文方法

    2024-01-18 20:02:39
  • MySQL学习笔记之数据的增、删、改实现方法

    2024-01-27 04:07:41
  • python Gunicorn服务器使用方法详解

    2021-09-06 00:35:08
  • python实现自动化上线脚本的示例

    2021-02-01 05:14:49
  • python scipy.misc.imsave()函数的用法说明

    2022-11-01 13:04:24
  • selenium+python配置chrome浏览器的选项的实现

    2022-06-24 11:56:31
  • python批量处理txt文件的实例代码

    2023-05-26 07:00:33
  • 使用SQL Server 2008远程链接时SQL数据库不成功的解决方法

    2024-01-29 09:15:46
  • Python中列表元素转为数字的方法分析

    2023-03-20 22:07:46
  • 简单获取键盘的KeyCode

    2008-04-18 12:37:00
  • Python内置数据结构列表与元组示例详解

    2021-08-17 21:28:14
  • Django+mysql配置与简单操作数据库实例代码

    2024-01-14 09:19:28
  • python logging.info在终端没输出的解决

    2022-04-15 20:39:52
  • 微信小程序如何处理token过期问题

    2023-07-02 05:23:54
  • 一文详解websocket在vue2中的封装使用

    2024-05-02 17:08:54
  • pandas 层次化索引的实现方法

    2023-11-24 19:04:02
  • JavaScript让Textarea支持tab按键的方法

    2024-05-05 09:15:00
  • asp之家 网络编程 m.aspxhome.com