day19-继承多态和静态方法和异常处理(10.14)
大概内容目录(最后重新整理):
- 定义类的步骤
- 魔术方法
- 异常处理机制
- 继承的重写和多态
1、练习1:分数类的编写
知识点:
1、函数求最大公约数法 - 欧几里得算法,辗转求余数法
2、自定义异常
3、魔术方法
def __add__(self)
,def __sub__(self)
,def __mul__(self)
,
def __floordiv__(self)
,def __truediv__(self)
4、@property 装饰器属性
5、魔术方法:
def __str__(self)
,def __repr__(self)
给类或类的对象添加打印值6、取绝对值:abs(数据) x,y = abs(self.num), abs(self.den)
2、自定义异常
raise关键字,引发异常,值错误异常 自定义类型异常,继承Exception,Exception异常,子类型也异常 通过继承Exception自定义异常(可以继承Exception,也可以继承Exception的子类) class FractionException(Exception): pass if den == 0: raise FractionException('分母不能为0')
3、魔术方法
def __add__(self)
,def __sub__(self)
,def __mul__(self)
,
def __floordiv__(self)
,def __truediv__(self)
对结果直接可以使用+,-,*,//,/进行运算符操作,eg: print(f1 * f2 + f1 - f2 / f1)
4、@property 装饰器属性
原本需要(.方法()使用,现在直接掉.属性),省略() """计算属性:通过对象现有的属性运算得到的一个值,本来是一个方法,但外面可以通过添加@property装饰器,将它处理成属性""" 加装饰器后变成属性,没有其他参数额外才可以使用@property(.属性),调用不用括号
5、魔术方法:
def __str__(self)
,def __repr__(self)
给类或类的对象添加打印值区别:这两个都用于显示内容,
__str__
是面向用户的,而__repr__
面向开发者。重构
__repr__
方法后,不管直接输出对象(面向开发者)还是通过print(面向用户)打印的信息都按我们__repr__
方法中定义的格式进行显示了想要直接输出对象(面向开发者)和使用 print 输入对象都显示的是友好提示除了重构
__repr__
,还可以重构__str__
实现。1) def __str__(self): # 输出打印/show也可 return f'{self.num}/{self.den}' # 比较好直接输出print(f1) #def show(self): # 比较麻烦需要 print(f1.show()) #return f'{self.num}/{self.den}' f1 = Fraction(1, 2) #print(f1.show()) print(f1) 2) def __repr__(self): # return f'({self.x},{self.y})' return f'<{self.x},{self.y}>' print(p1, p2)
day19练习1:分数,几分之几
属性:分子,分母
显示:
行为:分数各种运算,+,-,/
分数 - fraction
分子 - numerator
分母 - denominator
add / substract / multiply / divide +,-,,/
day19-作业练习:列表放整数,浮点数,求平均数,中位数,方差,标准差, mylist(继承+添加功能)
“”"
teacher 答案练习1:day19练习1:分数,几分之几
定义类,数据抽象,行为抽象(需要补充)
魔术方法 lt,str,repr(需要补充)
""" 1)最大公约数的举例说明: # x,y y % x == 0 --> 成立:返回x -->不成立:找 y%x,x的最大公约数(余数) 举例说明: 15 27 --> 12 15 --> 3 12 -->3 99999 99998-->1 99998 --> 1 """ # 忽略省掉:方法一不用:def gcd(x, y): # """最大公约数不用""" # for i in range(min(x, y), 1, -1): #** 向循环,1取不到,从-1开始取 # if x % i == 0 and y % i == 0: # return i # return 1
# 方法二常用:欧几里得算法,辗转求余数法
def gcd(x, y):
"""最大公约数,欧几里得算法,辗转求余数法(效率高)"""
while y % x != 0:
x, y = y % x, x
return x # 大小不影响会进行换位置
print(gcd(15, 27)) # 3
print(gcd(27, 15)) # 3
print(3 % 2) # 1
print(2 % 3) # 2
2)通过继承Exception自定义异常(可以继承Exception,也可以继承Exception的子类)(从头到尾来一遍,卡着的地方看完继续写local history->show-右键-revert恢复)
class FractionException(Exception):
pass # 自定义类型异常,继承Exception,Exception异常,子类型也异常
class Fraction:
@classmethod
def from_value(cls, value: float, base=10000):
"""小数变成分数 0.25"""
return cls(int(value * base), base) # 构造器语法 num,den
@classmethod
def from_string(cls, string: str): # csl类相当于Fraction,csl()构造器语法
"""字符串变分数 # ‘ 3 / 4 ’"""
# 法二
num, den = [int(item.strip()) for item in string.split('/')]
return cls(num, den)
# 法一:动作的拆解
# items = string.split('/')
# num, den = [int(item.strip()) for item in items]
# return cls(num, den)
# 2)综合num, den = map(int, map(str.strip,string.split('/')))#去左右两边的空格,以/拆分
def __init__(self, num, den):
if den == 0:
# 如果分母为0,直接引发异常让程序崩溃
# raise ValueError('分母不能为0') # raise关键字,引发异常,值错误异常
raise FractionException('分母不能为0') # raise关键字,引起异常 直接给值??
self.num = num
self.den = den
self.normalize()
self.simplify()
def __str__(self): # 输出打印/show也可
# if self.num == 0 or self.den == 1:
if self.den == 1:
return f'{self.num}'
return f'{self.num}/{self.den}'
def simplify(self):
"""化简"""
if self.num != 0:
# 取绝对值abs
x, y = abs(self.num), abs(self.den)
# 最大公约数(最大的公共的因子)
factor = gcd(x, y)
self.num, self.den = self.num // factor, self.den // factor # 整除最大公约数,分子,分母除以最大公约数
return self
# def add(self, other):
# """加法"""
# num = self.num * other.den + other.num * self.den
# den = self.den * other.den
# return Fraction(num, den) # 重新构造一个分数对象
def __add__(self, other): # 更新后直接使用运算符进行运算
"""加法"""
num = self.num * other.den + other.num * self.den
den = self.den * other.den
return Fraction(num, den) # 重新构造一个分数对象
def __sub__(self, other):
"""减法"""
num = self.num * other.den - other.num * self.den
den = self.den * other.den
return Fraction(num, den)
def __mul__(self, other):
"""乘法"""
num = self.num * other.num
den = self.den * other.den
return Fraction(num, den)
# def __floordiv__(self, other): # 对应除法的"//"
def __truediv__(self, other): # 对应除法的"/"
"""除法"""
num = self.num * other.den
den = self.den * other.num
return Fraction(num, den)
@property # 装饰器属性(掉属性.,掉方法.方法())
def value(self): # 下午新增(新增diqici保留几位小数)
"""分数变小数"""
"""计算属性:通过对象现有的属性运算得到的一个值,本来是一个方法,但外面可以通过添加@property装饰器,将它处理成属性"""
return self.num / self.den
def normalize(self):
"""规范化(分母负号)"""
if self.num == 0: # 新增if self.den == 1:
self.den = 1
elif self.den < 0:
self.num = -self.num
self.den = -self.den
return self # ?? self.normalize() self 分数对象
# self 解释:self指的是实列本身,f1 = Fraction(2, 4),f1就是self
# f1 = Fraction(1, 0) # 1 解决:raise FractionException('分母不能为0')
f1 = Fraction(0, -5) # 输出有问题需要解决,num=0,不用化简。解决if self.num != 0:才进行化简
print(f1)
# f1 = Fraction(4, -5) # -4/5
# f1 = Fraction(-4, -5) # 4/5
f1 = Fraction(2, 4)
print(f1) # 1/2
# f2 = Fraction(3, 4)
# print(f2.add(f1))
# f3 = f1.mul(f2)
# print(f3)
# f4 = f2.add(f1).add(f3)
# print(f4)
# print(f1.add(f2).mul(f3))
#更新方法__lt__,魔术方法,直接使用运算符号
f1 = Fraction(2, 4)
f2 = Fraction(3, 4)
print(f1)
print(f1 + f2)
print(f1 * f2)
print(f1 * f2 + f1 - f2 / f1)
f1 = f1 * f2
f1 *= f2
print(f1)
print((f1+f2)* f1 / f2)
# 1)调用方法
# print(f1.value())
# 2)加装饰器后变成属性,没有其他参数才可以使用@property(.属性),调用不用括号
print(f1.value)
# 字符串变分数
f1 = Fraction.from_value(0.25)
print(f1)
f2 = Fraction.from_string(' 2 / 3')
print(f2)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8BYqjaFx-1634295668840)(C:\Users\z\Desktop\tupian\10.14\2.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLsjJ7EL-1634295668843)(C:\Users\z\Desktop\tupian\10.14\5.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oKm39RJS-1634295668845)(C:\Users\z\Desktop\tupian\10.14\6.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gKNyncdP-1634295668848)(C:\Users\z\Desktop\tupian\10.14\7.jpg)]
2、python 中的异常处理机制
知识点:异常处理机制
“”"
python 中的异常处理机制:
异常状况处理-代码本身即便没有问题,但在运行时可能因为外部环境和资源的问题,
导致代码无法运行,程序出现异常状况,如果异常状况没有得到处理,那么程序就会崩溃
具体的表现就是代码直接停止运行。如果不希望程序崩溃,就要对代码进行异常状况的处理,
在python中,可以使用try(…except…)语法将可能出现状况的代码保护起来执行,在出现状况的时候
使用except进行异常状况捕获并给出相应的处理
异常关键字:
try,except,finally,raise,except里面还可以加else
“”"
# 异常捕获:读取文件操作可能预计不存在文件和读取文件内容失败的情况
import sys
import time
while True:
try: #避免运行出现问题,使用try保护起来(可能出现问题的代码使用try保护起来,其他异常在except Exception捕获)
with open('readme.txt') as file: # 文件自动关闭
print(file.read()) # FileNotFoundError
break
except FileNotFoundError: # 捕获异常
print('错误提示:文件不存在,5秒钟以后重新尝试读取文件')
time.sleep(5) # 文件不存在,5秒钟以后重新尝试读取文件
except IOError:
print('错误提示:读取文件失败,请确认设备是否就绪')
sys.exit(1) # u盘突然抽出,关闭Python解释器
# except: # 其他剩余异常 01法
except Exception: # 其他剩余异常 (Exception父类型可以捕获子类型的错误) 02法
print('错误提示:程序发生了一点小问题,请拨打400-800-8855寻求帮助')
sys.exit(1) # 程序直接退出
finally: # 总是执行代码
# file.close() # 关闭文件,断开网络
print('这个地方最适合释放外部资料')
print('程序结束') # 不管正常,异常都会执行finally
"""可以以下这样写但建议单独写异常问题"""
# except (FileNotFoundError, IOError):
# print('错误提示:文件不存在,5秒钟以后重新尝试读取文件')
# time.sleep(5)
# try,except..else,finally
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXTAMwVF-1634295668855)(C:\Users\z\Desktop\tupian\10.14\3.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pPPSVU4Y-1634295668856)(C:\Users\z\Desktop\tupian\10.14\4.jpg)]
3、工资(月薪)结算系统
知识点:
1.继承的重写
2.继承的多态
1)继承
2)override --> 重写 / 覆盖 / 置换 --> 子类将父类已有的方法重新写一遍
子类可以重写父类的方法,不同的子类可以对同一方法给出不同的实现版本
抽象类–> 拿来继承的 >>不用于创建类对象的 :ege:Employee
3)多态 - 不同的对象(员工:部门经理,销售员,程序员)接受到相同的消息(get_salary)做了不同的事情(工资结算?)
- 多态:不同的对象接受相同的消息做了不同的事情
要实现多态,最重要的一步就是方法重写,子类重写父类已有的方法,不同的子类给出了不同的实现版本
,所以这个方法在运行时就会表现出多态行为(接受消息是已有的,做的事情是不一样的
知识点:
1、@abstractmethod # 装饰器
@abstractmethod # 装饰器,父类方法变成抽象方法->让子类实现此方法 def get_salary(self): pass
2、
super().__init__(name)
调用父类初始化方法,属性比较多可以使用,和下面代码一样只有一个属性的时候可以是 super().__init__(name)或者self.name = name
3、子类如何添加属性
两种写法相同作用:想在子类添加一个新的属性,并给默认值。可以通过self.working_hour = 0给新增属性working_hour加默认值,括号中就不用添加形参working_hour。如果想在括号里直接赋值,那么就需要写出self.working_hour = working_hour。
#第一种: def __init__(self, name): self.name = name self.working_hour = 0 # 第二种: def __int__(self, name, working_hour=0): self.working_hour = working_hour
4、重写
override --> 重写 / 覆盖 / 置换 --> 子类将父类已有的方法重新写一遍 def get_salary(self): 父类 pass def get_salary(self): 子类 return 1800.0 + self.sales * 0.05
5、多态:
不同的对象接受相同的消息做了不同的事情
要实现多态,最重要的一步就是方法重写,子类重写父类已有的方法,不同的子类给出了不同的实现版本
,所以这个方法在运行时就会表现出多态行为(接受消息是已有的,做的事情是不一样的)print(f'{emp.name}工资是:{emp.get_salary():.2f}元')
“”
day18作业讲评-工资(月薪)结算系统(自己做的)
公司有三类员工,结算工资的方式是不一样的:
1.部门经理:15000元 / 月
2.程序员->计算工时–>200元/小时 * 本月工时
3.销售员 -> 底薪+提成 - > 1800元 + 本月销售额5%提出
给出员工信息列表,自动结算月薪
员工类
employee(员工),employer(雇主)
salary
manager
programmer
salesman
- 继承
2)override --> 重写 / 覆盖 / 置换 --> 子类将父类已有的方法重新写一遍
子类可以重写父类的方法,不同的子类可以对同一方法给出不同的实现版本
抽象类–> 拿来继承的 >>不用于创建类对象的 :ege:Employee
3)多态 - 不同的对象(员工:部门经理,销售员,程序员)接受到相同的消息(get_salary)做了不同的事情(工资结算?)
“”"
from abc import ABCMeta, abstractmethod # abc抽象,ABCMeta元类,抽象方法
class Employee(metaclass= ABCMeta): # 元类定义成抽象,不能创建对象
def __init__(self, name):
self.name = name
@abstractmethod # 装饰器,变成抽象方法->让子类实现此方法
def get_salary(self):
pass
class Manager(Employee):
def get_salary(self): # 方法重写
return 15000.0
class Programmer(Employee):
def __init__(self, name): # working_hour?
# super().__init__(name) 调用父类初始化方法,属性比较多可以使用,和下面代码一样
self.name = 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
def get_salary(self):
return 1800.0 + self.sales * 0.05
def main():
emps = [
Manager('曹操'), Programmer('诸葛亮'), Salesman('李典'),
Manager('曹植'), Programmer('曹总'), Salesman('小新')
]
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()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2aXlXqh-1634295668858)(C:\Users\z\Desktop\tupian\10.14\8.jpg)]
第一张图是父类,父类进行抽象化后不能进行使用,只能让子类用其中的方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Un9Fm8ug-1634295668859)(C:\Users\z\Desktop\tupian\10.14\9.jpg)]
4、day19作业练习
思路:
day19-作业练习:列表放整数,浮点数,求平均数,中位数,方差,标准差, mylist(继承+添加功能)
1、继承 2、表原来的基础上增加方法
掌握第二步,第三步
# # day19-作业练习:列表放整数,浮点数,求平均数,中位数,方差,标准差, mylist(继承+添加功能) # 1、继承 2、表原来的基础上增加方法 # 掌握第二步,第三步 # 自己做的练习题情况如下: import math class Mylist(list): def __init__(self, num: int or float): self.num = num self.average() self.variance() def __repr__(self): return f'{self.num}' def average(self): average = sum(nums for nums in self.num)/len(self.num) return average # 重新思考哪个地方需要返回什么样的值??怎么获取每个地方的值。 def Median(self): if len(self.num) % 2: new_num = sorted(self.num) t1 = new_num[len(new_num)//2] return t1 else: nem_num = sorted(self.num) t1 = (nem_num[len(nem_num)//2] + nem_num[len(nem_num)//2 - 1])/2 return t1 def variance(self): # 方差 sum1 = 0 # # average = sum(nums for nums in self.num) / len(self.num) for nums in self.num: sum1 += (nums-self.average())**2 v1 = sum1 / len(self.num) return v1 def standard_deviation(self):# 标准差=方差开根号 return math.sqrt(self.variance()) # ??思考self.variance()得到的是什么值???思考前面F(),返回的值到底是什么,使用网址看运行过程 mylist = Mylist([1,3, 5, 8, 1, 2]) print(mylist) # mylist.sort() # print(mylist) # print(mylist.Median()) print(mylist.variance()) print(mylist.standard_deviation()) print(mylist.average()) # 优化1:代码重复编写,average,v1,解决方法:self.variance()得到对应的值 mylist1 = Mylist([1.2, 1.9, 3, 4, 8]) print(mylist1) print(mylist1.average()) print(mylist1.Median()) print(mylist1.variance()) print(mylist.standard_deviation())
其他附录
1.分数运算:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bkQyM0Eb-1634295668860)(C:\Users\z\Desktop\tupian\10.14\1.jpg)]
问题思考:
# ??return self 本身-->self.simplify(),return Fraction(num, den)
csl具体是什么,再想一遍分数类
print(mylist)
print(mylist.Median())
print(mylist.variance())
print(mylist.standard_deviation())
print(mylist.average())优化1:代码重复编写,average,v1,解决方法:self.variance()得到对应的值
mylist1 = Mylist([1.2, 1.9, 3, 4, 8])
print(mylist1)
print(mylist1.average())
print(mylist1.Median())
print(mylist1.variance())
print(mylist.standard_deviation())
其他附录
1.分数运算:
[外链图片转存中…(img-bkQyM0Eb-1634295668860)]
问题思考:
# ??return self 本身-->self.simplify(),return Fraction(num, den)
csl具体是什么,再想一遍分数类