Skr-Eric的Python课堂(二十二)——Python的异常和运算符重载

2024-03-14 03:10

本文主要是介绍Skr-Eric的Python课堂(二十二)——Python的异常和运算符重载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

异常(高级)

  with 语句

    语法:

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

         语句块

  作用:

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

      如:文件打开后自动关闭,线程中锁的自动获取和释放等(线程后面会学)

  说明:

    as 子句中的变量用于绑定表达式执行后生成的对象

    with语句并不会改变异常的状态

 

  示例:

# 第一种方式用try-finally保证文件一定能够正常关闭
try:f = open("../../day19/day19.txt")try:for l in f:x = int('aaaa')  # 出现异常print(l)finally:f.close()print("文件已经关闭")
except OSError:print("打开文件失败")

  环境资源管理器

    1. 类内有 __enter__和 __exit__实例方法的类创建的对象被称为环境管理器

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

    3. __enter__方法将在进入with语句时被调用, 由as变量绑定返回的对象

    4. __exit__方法将在离开with语句时被自动调用,且可以通过参数来判断离开with语句时是否有异常发生

 

  示例:

# 此示例示意自定义的对象加入__enter__ 和 __exit__ 方法,让A类的对象能够使用with使用语句
class A:'''此类的对象可以用于with语句进行管理'''def __enter__(self):print("此方法是在with语句内执行的")return self  # self将 被 with 中的as 变量绑定def __exit__(self, exc_type, exc_val, exc_tb):'''exc_type 用来绑定错误类型,当没有异常发生时绑定Noneexc_val 用来绑定错误对象,当没有发生异常时绑定Noneexc_tb 用来绑定TraceBack对象,当没有异常时绑定None'''if exc_type is None:print("您已离开with语句,离开时没有发生任何异常")else:print("您已离开with语句")print("错误类型是:", exc_type)print("错误对象是:", exc_val)print('Traceback:', exc_tb)with A() as a:print("这是with语句内部的输出")int(input("请输入整数: "))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 hand side)  右手边

 

  说明:

    运算符重载方法及参数已经有固定的含义,不建议改变原的运算符的含义及参数的意义

 

  二元运算符的重载方法格式:

    def __xxx__(self, other):

        语句块

 

反向算术运算符的重载

  当运算符的左侧为内建类型时,右侧为自定义类型进行算术运算符运算时会出现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   幂运算

 

示例:

# 此示例示意反向算术运算符的重载
class MyList:def __init__(self, iterable=()):self.data = list(iterable)def __repr__(self):return "MyList(%s)" % self.datadef __add__(self, rhs):return MyList(self.data + rhs.data)def __mul__(self, rhs):'''rhs 为int类型, rhs.data 是不存在的'''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])L3 = 3 * L1
print(L3)

 

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

  以复合赋值算术运算符 x += y 为例, 此运算符会优先调用 x.__iadd__(y) 方法,如果没有__iadd__方法时会将复合赋值运算拆解为: x = x + y 然后调用 x = x.__add__(y) 方法,如果再不存在__add__ 方法则会触发TypeError类型的错误异常

 

复合算术运算符的重载:

    方法名                  运算符和表达式   说明

  __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

 

位相关运算符重载

    方法名                  运算符和表达式   说明

  __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=()):self.data = list(iterable)def __repr__(self):return "MyList(%s)" % self.datadef __neg__(self):G = (-x for x in self.data)return MyList(G)L1 = MyList([1, -2, 3, -4, 5])
L2 = -L1  # <<---此处会有错误
print(L2)  # MyList([-1, 2, -3, 4, -5])

 

in / not in 运算符重载

  格式:

    def __contains__(self, e):

        语句

 

  注: in / not in 返回布尔值 True/False

    当重载了__contains__后, in 和 not in 运算符都可用.

    not in 运算符的返回值与 in 相反

  示例:

# 此示例示意 in / not in 运算符的重载class MyList:def __init__(self, iterable=()):self.data = list(iterable)def __repr__(self):return "MyList(%s)" % self.datadef __contains__(self, e):# print("+++++++++")return True if e in self.data else False# return e in self.dataL1 = MyList([1, -2, 3, -4, 5])if 2 in L1:  # 等同于 if L1.__contains__(2):print("2在L1内")
else:print('2不在L1内')if 4 not in L1:  # 等同于 if not L1.__contains__(4)print("4不在L1内")
else:print("4在L1内")

 

索引和切片运算符重载方法:

  方法名                   运算符和表达式       说明

 __getitem__(self, i)     x = self[i]    索引/切片取值

 __setitem__(self, i, v)  self[i] = v    索引/切片赋值

 __delitem__(self, i)     del self[i]  del语句删除索引/切片

 

作用:

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

 

  示例:

from __future__ import unicode_literals# 此示例示意 in / not in 运算符的重载class MyList:def __init__(self, iterable=()):self.__data = list(iterable)def __repr__(self):return "MyList(%s)" % self.__datadef __getitem__(self, i):'索引取值,i绑定[]内的元素'print('i的值是:', i)return self.__data[i]  # 返回data绑定列表中的第i个元素def __setitem__(self, i, v):'''此方法可以让自定义的列表支持索引赋值操作'''print("__setitem__被调用, i=", i, 'v=', v)self.__data[i] = vdef __delitem__(self, i):self.__data.pop(i)  # del self.__data[i]L1 = MyList([1, -2, 3, -4, 5])
x = L1[3]  # 能否用索引来访问自定义的MyList类型的对象呢
print(x)L1[3] = 400  # 索引赋值
print(L1)del L1[3]
print(L1)  # MyList([1, -2, 3, 5])# 思考如下语句能执行吗?
print(L1[::2])  # 切片取值
# 此示例示意切片取值操作
class MyList:def __init__(self, iterable=()):self.__data = list(iterable)def __repr__(self):return "MyList(%s)" % self.__datadef __getitem__(self, i):print('i的值是:', i)if type(i) is int:print("用户正在用索引取值")elif type(i) is slice:print("用户正在用切片取值")print("切片的起点是:", i.start)print("切片的终点是:", i.stop)print("切片的步长是:", i.step)elif type(i) is str:print("用户正在用字符串进行索引操作")# raise KeyErrorreturn "你想用字符串做什么?"return self.__data[i]  # 返回data绑定列表中的第i个元素L1 = MyList([1, -2, 3, -4, 5])
print(L1[::2])  # 切片取值
print(L1["ABC"])

 

  slice构造函数

    作用:

      用于创建一个slice对象,此对于用于切片操作的传值

    格式:

      slice(start=None, stop=None, step=None)

    slice对象的实例属性:

      start  切片的起始值 默认为None

      stop   切片的终止值 默认为None

      step   切片的步长 默认为None

 

特性属性 @property

  实现其它语言所拥有的getter 和 setter功能

 

  作用:

    用来模拟一个属性

    通过@property装饰器,可以对模拟属性的赋值和取值加以控制

  示例:

from __future__ import unicode_literals
# property.pyclass Student:def __init__(self, s):self.__score = sdef setScore(self, s):'''此方法用设置值加以限制以保证数据的准确性setter是用来数据的'''if 0 <= s <= 100:self.__score = sdef getScore(self):'''getter 只用来获取数据'''return self.__scores = Student(50)
s.setScore(100)# s.score = 100
# print(s.score)
# s.score = 10000
# print(s.score)

 

 

课后习题:

  实现有序集合类OrderSet , 能实现两个集合的交集 &, 并集 |, 补集-, 对称补集 ^, ==,!=,in / not in 等操作

  要求: 集合的内部用list存储数据

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("不相等")
else:print("相等")
if s1 == OrderSet([3, 4, 5]):print("s1 == OrderSet([3, 4, 5])")
if 2 in s1:print('2 in s1 返回真')... 以下自己测试

 

 

 

想要看更多的课程请微信关注SkrEric的编程课堂

这篇关于Skr-Eric的Python课堂(二十二)——Python的异常和运算符重载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807029

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结