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):
return f'{self.num}/{self.den}'
f1 = Fraction(1, 2)
print(f1)
2)
def __repr__(self):
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))
print(gcd(27, 15))
print(3 % 2)
print(2 % 3)
2)通过继承Exception自定义异常(可以继承Exception,也可以继承Exception的子类)(从头到尾来一遍,卡着的地方看完继续写local history->show-右键-revert恢复)
class FractionException(Exception):
pass
class Fraction:
@classmethod
def from_value(cls, value: float, base=10000):
"""小数变成分数 0.25"""
return cls(int(value * base), base)
@classmethod
def from_string(cls, string: str):
"""字符串变分数 # ‘ 3 / 4 ’"""
num, den = [int(item.strip()) for item in string.split('/')]
return cls(num, den)
def __init__(self, num, den):
if den == 0:
raise FractionException('分母不能为0')
self.num = num
self.den = den
self.normalize()
self.simplify()
def __str__(self):
if self.den == 1:
return f'{self.num}'
return f'{self.num}/{self.den}'
def simplify(self):
"""化简"""
if self.num != 0:
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 __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 __truediv__(self, other):
"""除法"""
num = self.num * other.den
den = self.den * other.num
return Fraction(num, den)
@property
def value(self):
"""分数变小数"""
"""计算属性:通过对象现有的属性运算得到的一个值,本来是一个方法,但外面可以通过添加@property装饰器,将它处理成属性"""
return self.num / self.den
def normalize(self):
"""规范化(分母负号)"""
if self.num == 0:
self.den = 1
elif self.den < 0:
self.num = -self.num
self.den = -self.den
return self
f1 = Fraction(0, -5)
print(f1)
f1 = Fraction(2, 4)
print(f1)
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)
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:
with open('readme.txt') 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('程序结束')
"""可以以下这样写但建议单独写异常问题"""
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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
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):
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具体是什么,再想一遍分数类
|