day19-继承多态和静态方法和异常处理(10.14)

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. 多态:不同的对象接受相同的消息做了不同的事情
    要实现多态,最重要的一步就是方法重写,子类重写父类已有的方法,不同的子类给出了不同的实现版本
    ,所以这个方法在运行时就会表现出多态行为(接受消息是已有的,做的事情是不一样的

知识点:

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

  1. 继承
    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具体是什么,再想一遍分数类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值