【第19天】Python第一阶段学习总结
2021/10/14
一. Python中的异常处理机制
代码本身即便没有问题,但在运行时可能因为外部环境或资源的问题,导致代码无法运行,程序出现异常状况,如果异常状况没有得到处理,那么程序就会崩溃,具体的表现就是代码直接停止运行。
如果不希望程序崩溃,就要对代码进行异常状况的处理,在Python中,可以使用try语法将可能出现状况的代码保护起来执行,在出现状况的时候,使用except进行异常状况捕获并给出相应的处理。
1. try
- 用try语法将可能出现状况的代码保护起来执行
2. except
- 在出现状况的时候,使用except进行异常状况捕获并给出相应的处理
3. finally
- 实际项目中,此处通常用来释放外部资源(例如网络连接、数据库连接等),因为这里的代码在任何情况下一定会被执行到,这里的代码称为总执行代码
import sys
import time
while True:
try:
with open('readme.txt', encoding='utf-8') as file:
print(file.read())
break
except FileNotFoundError:
print('错误提示:文件不存在,5秒钟以后重新尝试读取文件')
time.sleep(5)
except IOError:
print('错误提示:读取文件失败,请确认设备是否就绪')
sys.exit(1)
except Exception:
print('错误提示:程序发生了一点小问题,请拨打400-800-8855寻求帮助')
sys.exit(1)
finally:
print('这个地方最适合放外部资源!!!')
print('程序结束')
二. 面对象编程进阶
1. 自定义异常
- 通过继承Exception自定义异常类型
- 自定义异常类型通常都是继承Exception类或者它的子类
- 自定义异常类型通常也不需要写什么代码,主要就是定义一种新的自定义的类型来标记特殊的异常状况,代码直接复用父类Exception的代码
- raise:关键字 - 引发;通过raise关键字,后面跟上异常对象引发异常,如果使用这个代码的人没有做异常处理,那么程序就会在这个地方崩溃
2. @property:计算属性
- 计算属性:通过对象现有的属性运算得到一个值,本来是一个方法,但是我们可以通过添加@property装饰器,将它处理成属性
def gcd(x, y):
"""求最大公约数"""
while y % x != 0:
x, y = y % x, x
return x
'''
1. 通过继承Exception自定义异常类型
2. 自定义异常类型通常都是继承Exception类或者它的子类
3. 自定义异常类型通常也不需要写什么代码,主要就是定义一种新的自定义的类型来标记特殊的异常状况,代码直接复用父类Exception的代码
'''
class FractionException(Exception):
pass
class Fraction:
@classmethod
def from_value(cls, value: float, base=10000):
return cls(int(value * base), base)
# '3 / 4'
@classmethod
def from_string(cls, string: str):
num, den = map(int, map(str.strip, string.split('/')))
# items = string.split('/')
# num, den = [int(item.strip()) for item in items]
# return cls(*[int(item.strip()) for item in string.split('/')]) # 解包语法
return cls(num, den)
def __init__(self, numerator, denominator):
# 如果分母为0,直接引发异常让程序崩溃
if denominator == 0:
# raise 关键字 - 引发; 通过raise关键字,后面跟上异常对象引发异常,如果使用这个代码的人没有做异常处理,那么程序就会在这个地方崩溃
raise FractionException('分母不能为0')
self.numerator = numerator
self.denominator = denominator
self.normalize()
self.simplify()
def __repr__(self):
if self.denominator == 1:
return f'{self.numerator}'
return f'{self.numerator}/{self.denominator}'
def simplify(self):
"""化简"""
if self.numerator != 0:
factor = gcd(abs(self.numerator), abs(self.denominator))
self.numerator, self.denominator = self.numerator // factor, self.denominator // factor
return self # 可以继续调用其他方法
def normalize(self):
"""规范化"""
if self.numerator == 0:
self.denominator = 1
elif self.denominator < 0:
self.numerator = - self.numerator
self.denominator = - self.denominator
return self
def __add__(self, other):
"""+"""
a = self.numerator
b = self.denominator
c = other.numerator
d = other.denominator
num = a * d + c * b
den = b * d
return Fraction(num, den)
def __sub__(self, other):
"""-"""
a = self.numerator
b = self.denominator
c = other.numerator
d = other.denominator
num = a * d - c * b
den = b * d
return Fraction(num, den)
def __mul__(self, other):
"""*"""
num = self.numerator * other.numerator
den = self.denominator * other.denominator
return Fraction(num, den)
def __truediv__(self, other):
"""/"""
num = self.numerator * other.denominator
den = self.denominator * other.numerator
return Fraction(num, den)
# @property:将方法变成属性,方法没有其他的参数才可以用
@property
def value(self):
"""分数转换成小数"""
# 计算属性:通过对象现有的属性运算得到的一个值,本来是一个方法,但是我们可以通过添加@property装饰器,将它处理成属性
return self.numerator / self.denominator
# f1 = Fraction(-6, 9)
f1 = Fraction.from_string('6 / 9')
print(f1)
# f2 = Fraction(3, -4)
f2 = Fraction.from_value(-0.75)
print(f2)
print(f1, f2)
print(f1 + f2)
print(f1 - f2)
print(f1 * f2)
f3 = f1 / f2
print(f3)
print(f3.numerator / f3.denominator)
print(f3.value)
3. 多态
- 元类:meta class
- 抽象类:abstract class
- 实现多态,最重要的一步就是方法重写,子类重写父类已有的方法,不同的子类给出了不同的实现版本,所以这个方法在运行时就会表现多态行为(接受消息是一样的,做的事情是不一样的)
- override —> 重写 / 覆盖 / 置换 —> 子类将父类已有的方法重写写一遍
- 子类可以重写父类的方法,不同的子类可以对同一个方法给出不同的实现版本
- 多态:不同的对象(部门经理,销售员,程序员)接收到相同的消息(get_salary)做了不同的事情(每月工资不一样)
from abc import ABCMeta, abstractmethod
class Employee(metaclass=ABCMeta):
"""员工"""
def __init__(self, name):
"""初始化方法
:param name: 员工姓名
"""
self.name = name
@abstractmethod
def get_salary(self):
pass
class Manager(Employee):
"""经理"""
def __init__(self, name):
super().__init__(name)
def get_salary(self):
return 15000.0
class Programmer(Employee):
def __init__(self, name):
super().__init__(name)
self.working_hour = 0
def get_salary(self):
return 200 * self.working_hour
class Salesman(Employee):
def __init__(self, name):
super().__init__(name)
self.sales = 0.0
def get_salary(self):
return 1800.0 + self.sales * 0.05
def main():
emps = [
Manager('曹操'), Programmer('荀彧'), Programmer('郭嘉'), Salesman('典韦'), Salesman('曹仁'), Programmer('李典')
]
for emp in emps:
if type(emp) == Programmer:
emp.working_hour = int(input(f'请输入{emp.name}本月工作时间:'))
elif type(emp) == Salesman:
emp.sales = float(input(f'请输入{emp.name}本月销售额:'))
print(f'{emp.name}本月工资为:{emp.get_salary():,.2f}元')
if __name__ == '__main__':
main()