Python第二阶段第一章笔记(对象)

第一章初识对象

生活中数据的组织

程序中数据的组织

可以发现 :混乱不统一

思考一个问题:

使用变量记录数据太乱了。

如果程序中也和生活中一样

。可以设计表格

。可以将设计的表格打印出来

。可以将打印好的表格供人填写内容

那么数据的组织就非常方便了。

使用对象组织数据

在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的。

  1. 在程序中设计表格,我们称之为: 设计类
  2. 在程序中打印生产表格,我们称之为: 创建对象
  3. 在程序中填写表格,我们称之为: 对象属性赋值

比如在程序内去做这个表:

 #先创建一个类,也就是设计一个表单,并对里面(栏)对象使用变量接收(可以用None)

class Students:

    name = None

    gender = None

    nationly = None

    countyside = None

    age = None

#表设计好了,该打印出来了,也就是获取到这个对象

stu_1 = Students()

#下一步去给这些变量赋值,填写内容

stu_1.name = "康一"

stu_1.gender = "男"

stu_1.nationly = "日本"

stu_1.countyside = "杜王瞳"

stu_1.age = 18

#打印出来

print(stu_1.name)

print(stu_1.gender)

print(stu_1.nationly)

print(stu_1.countyside)

print(stu_1.age)

总结

1.生活中或是程序中,我们都可以使用设计表格、生产表格、填写表格的形式组织数据

2.进行对比,在程序中:

设计表格,称之为:设计类 (class)

打印表格,称之为;创建对象

填写表格,称之为;对象属性赋值

成员方法

类的定义和使用

在上一节中,我们简单了解到可以使用类去封装属性,并基于类创建出一个个的对象来使用现在我们来看看类的使用语法:

 创建类对象的语法:

对象 = 类名称()

成员变量和成员方法

那么,什么是类的行为(方法)呢?

 可以看出,类中:

 不仅可以定义属性用来记录数据也可以定义函数,用来记录行为

其中:

中定义的属性(变量),我们称之为:成员变量

中定义的行为(函数),我们称之为:成员方法

方法就是定义在类内部的函数!

而函数就是定义在类之外的!

成员方法的定义语法

可以看到,在方法定义的参数列表中,有一个:

self关键字self关键字是成员方法定义的时候,必须填写的。

它用来表示类对象自身的意思

当我们使用类对象调用方法的时候,self会自动被python传入在方法内部;

想要访问类的成员变量,必须使用self

注意事项:

self关键字,尽管在参数列表中,但是传参的时候可以忽略它

 而msg是我自定的形式参数,调用的时候需要传入参数!

可以看到,在传入参数的时候,self是透明的,可以不用理会它

 而且,self是自己出现的

测试案例:

#定义一个类,包括方法(行为),和属性

class Student:

    name =  None

    def say_hi(self):

        print(f"大家好,我是{self.name},请多多关照")

#得到类对象

stu = Student()

#填表格了

stu.name = "奥特曼"

stu.say_hi()



stu2 = Student()

stu2.name = "康一"

stu2.say_hi()

测试(传入参数的使用)2:

#定义一个类,包括方法(行为),和属性

class Student:

    name =  None



    def say_hi(self):

        print(f"大家好,我是{self.name},请多多关照")

    def say_hi2(self,ms):

        print(f"大家好,我是{self.name},{ms}")  #ms不是类内的数据,不需要self

#得到类对象

stu = Student()

#填表格了

stu.name = "东方仗助"

stu.say_hi2("让你看看什么是不灭钻石")



stu2 = Student()

stu2.name = "康一"

stu2.say_hi2("看我的回音ACT2")

总结

  

类和对象

现实世界的事物和类

现实世界的事物也有属性和行为,类也有属性和行为

使用程序中的类,可以完美的描述现实世界的事物

基于类创建对象的语法:对象名 = 类名称()

为什么非要创建对象才能使用呢?

因为类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象 ),才能正常工作,这种套路,称之为 :面向对象编程

使用类和对象描述现实事物

程序中通过类来描述

基于类创建对象

 这就是面向对象编程:设计类,基于类创建对象,由对象做具体的工作

也就是图纸(类)设计好了,基于类去创建对象,让对象(生产的闹钟)去真正的干活!

例子如下:

#设计图纸(类),添加属性以及行为方法

class Clock:

    id = None

    price = None



    def ring(self):

        import winsound

        winsound.Beep(2000,3000)



#基于类去创造对象

clock1 = Clock()



#让对象去做工作

clock1.id = "11011"

clock1.price ="21.22"

print(f"闹钟id为{clock1.id},价格为{clock1.price}")

clock1.ring()



#基于类去创建第二个对象

clock2 = Clock()

#让对象去做工作

clock2.id = "11011"

clock2.price ="21.22"

print(f"闹钟id为{clock1.id},价格为{clock1.price}")

clock2.ring()

总结:

现实世界的事物由什么组成?

属性

行为

类也可以包含属性和行为,所以使用类描述现实世界事物是非常合适的

类和对象的关系是什么?

类是程序中的“设计图纸”

对象是基于图纸生产的具体实体

什么是面向对象编程?

面向对象编程就是,使用对象进行编程即,设计类,基于类创建对象,并使用对象来完成具体的工作

构造方法

掌握使用构造方法向成员变量赋值

属性(成员变量)的赋值

 思考: student()

这个括号,能否像函数(方法)那样,通过传参的形式对属性赋值呢?

可以,需要使用构造方法:_init__()

构造方法

Python类可以使用:__ init__ ()方法,称之为构造方法

可以实现:

创建类对象(构造类)的时候,会自动执行

创建类对象(构造类)的时候,将传入参数自动传递给_init_方法使用

 

 例子如下:

class Student:

    # name = None

    # age = None

    # tel = None

    def __init__(self,name,age,tel):

        self.name = name

        self.age = age

        self.tel= tel

        print("看我的行为在构建好类对象之后会不会第一个执行,在构建stu = student()的时候就自动执行了")


stu = Student("康一",21,"21312313")

print(stu.name)

print(stu.age)

print(stu.tel)

构造方法注意事项

总结:

构造方法的名称是:

init_,注意init前后的2个下划线符号

构造方法的作用

构建类对象的时候会自动运行

构建类对象的传参会传递给构造方法,借此特性可以给成员变量赋值

注意事项:

构造方法不要忘记self关键字

在方法内使用成员变量需要使用self

小练习

我写的:没有使用类,单纯使用了for循环

class Student:



    for i in range(1,11):

        print(f"当前录入第{i}位学生信息,共有10名")

        name = input("请输入您的姓名:")

        age = input("请输入您的年龄:")

        address = input("请输入您的地址:")

        def __init__(self,name,age,address):

            self.name = name

            self.age = age

            self.address = address



        print(f"学生{i}的信息录入完成,信息为:[学生姓名:{name},年龄:{age},地址:{address}]")

更新使用类的层面来做:

class Student:

    # name = None

    # age = None

    # address = None

    def __init__(self, name, age, address):

            self.name = name

            self.age = age

            self.address = address

for i in range(1,11):

    print(f"当前录入第{i}位学生信息,共有10名")

    stu = Student(

            name = input("请输入你的姓名:"),

            age = input("请输入你的年龄:"),

            address=input("请输入你的地址:"),

    )

    print(f"学生{i}的信息录入完成,信息为:[学生姓名:{stu.name},年龄:{stu.age},地址:{stu.address}]")

其它内置方法

魔术方法

上文学习的_init_构造方法,是Python类内置的方法之一这些内置的类方法,各自有各自特殊的功能,这些内置方法我们称之为:魔术方法

所谓的模式方法都是在构建的类下面告诉编辑器一个什么是对的,返回是True,与之相反的就是False

_str_字符串方法

内存地址没有多大作用,我们可以通过_str_方法,控制类转换为字符串的行为

 这是因为在输出类对象的时候,在类对象的内部没有切换为字符串表示的方法存在,所以在写代码的时候就只会返回内存空间

class Student:

    def __init__(self,name,age):
        self.name = name
        self.age = age
    #构建字符串的魔术方法
    def __str__(self):
        return f"我的名字叫做{self.name},年龄为{self.age}"
#构建类对象
stu = Student("卫宫士郎",21)
print(stu)
print(str(stu))

__lt__小于符号比较方法(LT)

这是因为你在类的内部并没有定义如何比较导致的,类不知道比什么,如何比。

直接对2个对象进行比较是不可以的,但是在类中实现__lt__方法,即可同时完成:小于符号 和 大于符号 2种比较

 class Student:

    def __init__(self,name,age):
        self.name = name
        self.age = age
    #构建__lt__的模式方法
    def __lt__(self,other):
        return self.age < other.age
#构建类对象
stu1 = Student("卫宫士郎",21)
stu2 = Student("远坂凛",32)
print(stu1 < stu2)

print(stu1 > stu2)

_le_小于等于比较符号方法

 class Student:

    def __init__(self,name,age):
        self.name = name
        self.age = age
    #构建小于等于或者大于等于的魔术方法
    def __le__(self,other):
        return self.age <= other.age
#构建类对象
stu1 = Student("卫宫士郎",21)
stu2 = Student("远坂凛",32)
print(stu1 <= stu2)
print(stu1 >= stu2)

 都是与之对应的,比如le就只能比大小,不能带等于号

_eq_,比较运算符实现方法

不实现_eq_方法,对象之间可以比较,但是是比较内存地址;也即是:不同对象==比较一定是False结果(因为是内存地址不会一样)

实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了。

class Student:

    def __init__(self,name,age):
        self.name = name
        self.age = age
    #构建比较运算符实现方法
    def __eq__(self,other):
        return self.age == other.age
#构建类对象
stu1 = Student("卫宫士郎",21)
stu2 = Student("远坂凛",21)
print(stu1 == stu2)

总结:

封装

面向对象的三大特性

面向对象编程,是许多编程语言都支持的一种编程思想。

简单理解是:基于模板(类)去创建实体(对象),使用对象完成功能开发

面向对象包含3大主要特性: 封装;继承;多态

封装表示的是,将现实世界事物的:

属性

行为

封装到类中,描述为:

成员变量

成员方法

从而完成程序对现实世界事物的描述

对用户隐藏的属性和行为

现实世界中的事物,有属性和行为。但是不代表这些属性和行为都是开放给用户使用的

苹果越狱、安卓root,也是为了突破权限使用这些对用户隐藏的属性和行为

私有成员

既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持有隐藏的属性存在。

类中提供了私有成员的形式来支持。

私有成员变量

私有成员方法

定义私有成员的方式非常简单,只需要:

私有成员变量:变量名以__开头(2个下划线)

私有成员方法:方法名以__开头(2个下划线)

即可完成私有成员的设置

使用私有成员

 

 私有成员无法被类对象使用,但是可以被其它的成员(在类的内部可以)使用.

例如:你运行程序的时候,是不是需要cpu;内存的资源调度?...

class  Phone:

    __current_voltage = 0.5 #当前手机运行电压

    def __keep_Single_core(self):
        print("让手机使用单核运行")

    def call_by_5G(self):
        if self.__current_voltage >= 1:
            print("5G通话已开启")
        else:
            self.__keep_Single_core()
            print("电量不足,已更换单核模式运行")
phone=Phone()
phone.call_by_5G()

总结:

封装的概念是指?

现实世界事物在类中描述为属性和方法,即为封装。

什么是私有成员?为什么需要私有成员?

现实事物有部分属性和行为是不公开对使用者开放的

同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了

如何定义私有成员?

成员变量和成员方法的命名均以__(2个下划线)作为开头即可

私有成员的访问限制?

类对象无法访问私有成员

类中的其它成员可以访问私有成员

私有成员的定义我们已经了解了,但是它有什么实际的意义吗?

在类中提供仅供内部使用的属性 和方法而不对外开放(类对象无法使用 )

小练习

作答:

 发现私有用户是无法被类外面调用的,私有用户只能被类内部去调用

class Phone:
    __is_5g_enable = False
    def __check_5g(self):
        if self.__is_5g_enable == True:
            print("5g已开启")
        else:
            print("5g已关闭,开启4g")
    def call_by_5g(self):
        if self.__check_5g() ==True:
            print("正在通话中")
        else:
            print("正在通话中")
phone = Phone()
phone.call_by_5g()

老师写的:

class Phone:

    __is_5g_enable = False

    def __check_5g(self):
        if self.__is_5g_enable :
            print("5g已开启")
        else:
            print("5g已关闭,开启4g")
    def call_by_5g(self):
        self.__check_5g()
        print("正在通话中")

phone = Phone()
phone.call_by_5g()

总结:

封装的概念是指?

现实世界事物在类中描述为属性和方法,即为封装。

什么是私有成员?为什么需要私有成员?

现实事物有部分属性和行为是不公开对使用者开放的

同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了

如何定义私有成员?

成员变量和成员方法的命名均以__(2个下划线)作为开头即可

私有成员的访问限制?

类对象无法访问私有成员

类中的其它成员可以访问私有成员

私有成员的定义我们已经了解了,但是它有什么实际的意义吗?

在类中提供仅供内部使用的属性 和方法而不对外开放(类对象无法使用 )

小练习

作答:

发现私有用户是无法被类外面调用的,私有用户只能被类内部去调用

class Phone:
    __is_5g_enable = False
    def __check_5g(self):
        if self.__is_5g_enable == True:
            print("5g已开启")
        else:
            print("5g已关闭,开启4g")
    def call_by_5g(self):
        if self.__check_5g() ==True:
            print("正在通话中")
        else:
            print("正在通话中")
phone = Phone()
phone.call_by_5g()

老师写的:

class Phone:

    __is_5g_enable = False

    def __check_5g(self):
        if self.__is_5g_enable :
            print("5g已开启")
        else:
            print("5g已关闭,开启4g")
    def call_by_5g(self):
        self.__check_5g()
        print("正在通话中")

phone = Phone()
phone.call_by_5g()

继承

继承的引出

 

 这样写也略显繁琐~

单继承

 这样的是重新定义了一个类来做的,略显繁琐。

这是使用继承的来做的,只是增加了新的功能。

但是在做新的类的时候,类似传参的功能继承了之前旧的类的老功能

语法格式:

继承分为:单继承多继承

使用如图语法,可以完成类的单继承。

继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有)

class Phone:
    IMEI = None
    producer = "AT"
    def call_by_4g(self):
        print("4g通话功能")

#2022年的新版有了faceid以及5g通话
class Phone2022(Phone):
    face_id = "10086"

    def call_by_5g(self):
        print("5g通话功能")


phone = Phone2022()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()

多继承

Python的类之间也支持多继承,即一个类,可以继承多个父类

语法格式:

#多继承的演示
class Phone:
    IMEI = None
    producer = "AT"
    def call_by_4g(self):
        print("4g通话功能")

class NFCread:
    nfctype = "11"

    def read_card(self):
        print("NFC读卡功能")

    def write_card(self):
        print("NFC写卡功能")

class Remotion:

    def HWcheck(self):
        print("红外检查功能")

#定义完了功能,然后开始多继承,用逗号隔开
class Myphone2023(Phone,NFCread,Remotion):
    pass            #pass关键字是补全语法的!

myphone = Myphone2023()
myphone.call_by_4g() #具备phone的功能
myphone.read_card()  #具备NFC的功能
myphone.HWcheck() #红外检查的功能

多继承的注意事项

多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级

即:先继承的保留,后继承的被覆盖

就是说定义的类里面的成员有同名的,先继承哪个?

成员变量和成员方法都是。

 总结:

什么是继承?

继承就是一个类,继承另外一个类的成员变量和成员方法

语法:

class 类(父类[,父类2,......,父类N]):

类内容体

子类构建的类对象,可以

有自己的成员变量和成员方法

使用父类的成员变量和成员方法

单继承和多继承

单继承:一个类继承另一个类

多继承:一个类继承多个类,按照顺序从左向右依次继承

多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承

pass关键字的作用是什么

pass是占位语句

用来保证函数(方法)或类定义的完整性,表示无内容,空的意思

继承之复写

子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。

即:在子类中重新定义同名的属性或方法即可。

#复写的演示
class Phone:
    IMEI = "10086"
    producer = "ITCASTTTTT"
    def call_by_g(self):
        print("4g通话功能")


class Myphoen2023(Phone):
    IMEI = "2017099"

    def call_by_g(self):
        print("开启5g通话,4g关闭")

myphone = Myphoen2023()
myphone.call_by_g()
print(myphone.IMEI)

调用父类同名成员

一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员如果需要使用被复写的父类的成员,需要特殊的调用方式:

因为复写了之后,直接调用的话,调用的是复写后的子类,那么如何调用父类的的成员变量以及方法呢?

方式1:

调用父类成员

使用成员变量:父类名.成员变量

使用成员方法:父类名.成员方法(self)

方式2:

使用super()调用父类成员

使用成员变量:super().成员变量

使用成员方法:super().成员方法()

 

#调用父类的演示
class Phone:
    IMEI = "父类编号10086"
    producer = "父类制造厂商ITCASTTTTT"
    def call_by_g(self):
        print("父类4g通话功能")


class Myphoen2023(Phone):
    IMEI = "2017099"

    def call_by_g(self):
        print("开启5g通话,4g关闭")
        #可以在子类里也可以直接调用
        #看一下父类的厂商:方式一
        print(f"{Phone.producer}")
        Phone.call_by_g(self)

        # 方式二
        print(super().producer)
        super().call_by_g()


myphone = Myphoen2023()
myphone.call_by_g()

总结:

复写表示

对父类的成员属性或成员方法进行重新定义

复写的语法:

在子类中重新实现同名成员方法或成员属性即可

在子类中,如何调用父类成员

方式1:

调用父类成员

使用成员变量:父类名,成员变量使用成员方法:父类名,成员方法(self)

方式2:

使用super()调用父类成员

使用成员变量:super(),成员变量使用成员方法: super(),成员方法()

注意:只可以在子类内部调用父类的同名成员,子类的实体类对象调用默认是调用子类复写的

类型注解

变量的类型注解

为什么需要类型注解

思考,为什么Pycharm工具能够做到这一点?它是如何知道这个对象有append方法?

因为 :PyCharm确定这个对象,是list类型

同样,我们换一份代码:

定义一个函数func,接收一个参数data

你会发现,PyCharm不会在做出任何提示了

思考,为什么PyCharm工具无法提示了?

因为 :PyCharm不确定这个对象data是什么类型

又或者当我们调用方法,进行传参的时候(快捷键ctrl+ p弹出提示)

为什么内置模块random的方法可以提示类型自己定义的就不可以?

因为PyCharm无法通过代码确定应传入什么类型,我们需要使用类型注解

Python在3.5版本的时候引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。

类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)

主要功能

帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示

帮助开发者自身对变量进行类型注释

支持:

变量的类型注解

函数(方法)形参列表返回值的类型注解

为变量设置类型注解

 

除了使用 变量: 类型,这种语法做注解外,也可以在注释中进行类型注解。

语法:

#type:类型

类型注解的限制

类型注解主要功能在于:

帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示

帮助开发者自身对变量进行类型注释(备注)

并不会真正的对类型做验证和判断。

也就是,类型注解仅仅是提示性的,不是决定性的

如图代码,是不会报错的哦

"""
演示变量的类型注解
"""

# 基础数据类型注解
import json
import random
#
# var_1: int = 10
# var_2: str = "wsaotm"
# var_3: bool = True

# 类对象类型注解
class Student:
    pass
stu: Student = Student()

# 基础容器类型注解
# my_list: list = [1, 2, 3]
# my_tuple: tuple = (1, 2, 3)
# my_dict: dict = {"wsaotem": 666}


# 容器类型详细注解
my_list: list[int] = [1, 2, 3]
my_tuple: tuple[int, str, bool] = (1, "wsaotm", True)
my_dict: dict[str, int] = {"wsatm": 666}


# 在注释中进行类型注解
var_1 = random.randint(1, 10)   # type: int
var_2 = json.loads('{"name": "zhangsan"}')  # type: dict[str, str]

def func():
    return 10
var_3 = func()  # type: int
# 类型注解的限制
var_4: int = "itheima"
var_5: str = 123

总结:

什么是类型注解,有什么作用?

在代码中涉及数据交互之时,对数据类型进行显式的说明,可以帮助:

PyCharm等开发工具对代码做类型推断协助做代码提示

开发者自身做类型的备注

类型注解支持:

变量的类型注解

函数(方法)的形参和返回值的类型注解

变量的类型注解语法

语法1: 变量:类型

语法2: 在注释中,# type: 类型

注意事项

类型注解只是提示性的,并非决定性的。数据类型和注解类型无法对应也不会

导致错误

函数(方法)的类型注解

形参注解

 如图所示:

在编写函数(方法),使用形参data的时候,工具没有任何提示

在调用函数(方法),传入参数的时候,工具无法提示参数类型

这些都是因为,我们在定义函数(方法)的时候,没有给形参进行注解。

 例如:

下次再使用的时候:

 

返回值注解

同时,函数(方法)的返回值也是可以添加类型注解的。语法如下:

->:

 

注意,返回值类型注解的符号使用: ->

Union类型

 

那么这样的该如何添加注解呢?

Union类型表示:在里面的数据类型,要么是什么 ,要么是什么,2选1.

使用Union[类型,......,类型]可以定义联合类型注解

Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用

当一个数据容器内存放的元素不仅仅是一个类型的时候,用union来做注解

#演示union类型

from typing import Union

my_test : list[Union[str,int]] = [1,2,"saber","archer"]

#定义函数或者方法
def func(data:Union[int,str]) -> Union[str,int]:
    pass

func()

总结

什么是Union类型?

使用Union可以定义联合类型注解

Union的使用方式

导包: from typingimport Union

使用:Union[类型,......,类型]

多态

多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。

如何理解?

继承和复写的思想

多态常作用在继承关系

比如

函数(方法)形参声明接收父类对象

实际传入父类的子类对象进行工作

即:

父类做定义声明

子类做实际工作

用以获得同一行为,不同状态

#多态的演示

class Animal:
    def speak(self):
        pass

class Dog(Animal):  #这相当于继承和复写
    def speak(self):
        print("汪汪汪")

class Cat(Animal): #这相当于继承和复写
    def speak(se1f):
        print("喵喵喵")

def make_noise(animal:Animal): #定义了一个形参,类型为Animal
    animal.speak()

#使用两个子类来调用函数
dog = Dog()
cat = Cat()

make_noise(dog)
make_noise(cat)

抽象类(接口)

细心的同学可能发现了,父类Animal的speak方法,是空实现。

这种设计的含义是:

父类用来确定有哪些方法

具体的方法实现由子类自行决定

这种写法,就叫做抽象类(也可以称之为接口)

抽象类:含有抽象方法的类称之为抽象类

抽象方法:方法体是空实现的 (pass)称之为抽象方法

抽象类就好比定义一个标准包含了一些抽象的方法,要求子类必须实现

然后由这个顶层标准来制定了两个子类,子类去实际去做事情。

 配合多态来实现具体的功能

# 前不灿象类class AC: 这个就相当于一个顶层标准
class AC:
    def coolwind(self):
        """制冷"""
        pass

    def hot_wind(self):
        """制热"""
        pass

    def swing_l_r(self):
        """左右摆风"""
        pass

#因为AC是空实现,无法真正的工作,所以需要调用子类的实际行为来工作
class Midea_AC(AC):
    def coolwind(self):
        print("美的空调制冷")

    def hot_wind(self):
        print("美的空调制热")

    def swing_l_r(self):
        print("美的空调左右摆风")

class GREE_AC(AC):
    def coolwind(self):
        print("格力空调制冷")

    def hot_wind(self):
        print("格力空调制热")

    def swing_l_r(self):
        print("格力空调左右摆风")

#靠子类来真正来做了行为

def make_cool(ac:AC):
    ac.coolwind()
#构建子类的对象,制造空调,AC不构建,因为是空实现
midea = Midea_AC()
gree = GREE_AC()

make_cool(midea)
make_cool(gree)

总结:

什么是多态?

多态指的是,同一个行为,使用不同的对象获得不同的状态。

如,定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行工作,从而获得不同的工作状态

什么是抽象类(接口)

包含抽象方法的类,称之为抽象类。

抽象方法是指: 没有具体实现的方法(pass)称之为抽象方法

象类的作用

多用于做顶层设计(设计标准),以便子类做具体实现也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法并配合多态使用,获得不同的工作状态。

综合案例

需求分析

"""
面向对象,数据分析案例,主业务逻辑代码
实现步骤:
1. 设计一个类,可以完成数据的封奖
2. 设计一个抽象类,定义文件读服的相关功能,并使用子类实现具体功能
(为什么使用抽象类,因为有两个文本,但是文本不一样,一个csv一个json,那么就先定义一个标准父类做空实现只定义功能,具体再构造两个文本的子类)
3.读取文件,生产数据对象
4. 进行数据需求的逻耕计第《计算每一天的销售额)
5,通过PyEcharts进行图形绘制
"""

"""
数据定义的类
1. 设计一个类,可以完成数据的封奖
"""
class Record:
    #定义成员变量,看了一下文件有四列,所以我们定制4个成员变量,两种方法
    # date = None
    # order_id = None
    # money = None
    # province = None

    #第二种方法:构造方法!这个可以直接可以取值,推荐使用这个
    def __init__(self,date,order_id,money,province):
        self.date = date #订单日期
        self.order_id = order_id #订单id
        self.money = money #金额
        self.province = province #省份

    def __str__(self):
        return f"{self.date},{self.order_id},{self.money},{self.province}"

 

"""
2. 设计一个抽象类,定义文件读服的相关功能,并使用子类实现具体功能
(为什么使用抽象类,因为有两个文本,但是文本不一样,一个csv一个json,那么就先定义一个标准父类做空实现只定义功能,具体再构造两个文本的子类)
"""
import json

#定义一个抽线类,做顶层设计,确定功能
from data_define import Record
class FileReader:

    def read_data(self) -> list[Record]: #这里如果不导包的话会报错,因为这里没有record的类
            #读文件的数据,读到的每一条数都转换为Record对象(Record层面已经使用了构造方法,直接成为了对象),将它们都封装ist内返回即可
            pass

#开始第一个子类,csv文本类
class TextFileReader(FileReader):

    def __init__(self,path):
        self.path = path #定义成员变量记录文件的路径

    #实现复写,也就是具体子类做事
    def read_data(self) -> list[Record]:
        f = open(self.path,"r",encoding="UTF-8")
        record_list:list[Record] = [] #搞一个新的列表,从txt文件内取到的值直接append到这里来
        for line in f.readlines():
            line = line.strip() #消除读到的每一行的 换行符
            data_list = line = line.split(',') #以逗号隔开
            #构建类对象,根据下标,传入4个参数
            record = Record(data_list[0],data_list[1],int(data_list[2]),data_list[3])
            record_list.append(record)  #封装到了list里面

        f.close()
        return record_list

class JsonFileReader(FileReader):

    def __init__(self,path):
        self.path = path #定义成员变量记录文件的路径

    #实现复写,也就是具体子类做事
    def read_data(self) -> list[Record]:
        f = open(self.path,"r",encoding="UTF-8")
        record_list:list[Record] = []
        for line in f.readlines():
            data_dict = json.loads(line)  #json文件直接loads成为字典对象
            record = Record(data_dict['date'],data_dict['order_id'],int(data_dict['money']),data_dict['province'])
            record_list.append(record)

        f.close()
        return record_list





if __name__=='__main__':
    text_file_reader = TextFileReader("D:/2011年1月销售数据.txt")
    json_file_reader=JsonFileReader("D:/2011年2月销售数据JSON.txt")
    list1 = text_file_reader.read_data()
    list2 = json_file_reader.read_data()

    for l in list1:
        print(l)
    for l in list2:
        print(l)

"""
面向对象,数据分析案例,主业务逻辑代码
实现步骤:
1. 设计一个类,可以完成数据的封奖
2. 设计一个抽象类,定义文件读服的相关功能,并使用子类实现具体功能
(为什么使用抽象类,因为有两个文本,但是文本不一样,一个csv一个json,那么就先定义一个标准父类做空实现只定义功能,具体再构造两个文本的子类)
3.读取文件,生产数据对象
4. 进行数据需求的逻耕计第《计算每一天的销售额)
5,通过PyEcharts进行图形绘制
"""


#3.读取文件,生产数据对象
#导入之前所有的包
from file_define import FileReader,TextFileReader,JsonFileReader
from  data_define import Record
from pyecharts.charts import Bar
from pyecharts.options import *
from pyecharts.globals import ThemeType
#生成数据对象
text_file_reader = TextFileReader("D:/2011年1月销售数据.txt")
json_file_reader=JsonFileReader("D:/2011年2月销售数据JSON.txt")

jan_data :list[Record]= text_file_reader.read_data() #1月份的数据
feb_data :list[Record] = json_file_reader.read_data() #2月的数据

#现将两个月份的数据合并为一个list
all_data:list[Record] = jan_data + feb_data

# 4;进行数据需求的逻耕计第《计算每一天的销售额)
#如何进行计算呢,使用字典的kv来进行,比如{2021-1-3 : 金额,“2021-1-4:金额....”}
# 是这一天的就for循环进行累加,且返回的是list列表的record对象,在其他上面定义了的构造方法
#判断有没有这个key有的话就拿取value进行累加,没有就取
data_dict = {}
for record in all_data:
    if record.date in data_dict.keys():
        #当前日期已经有记录了,所以直接相加即可 ,字典的key可以取到对应的value,再和有了这个日期的money累加进行覆盖
        data_dict[record.date] += record.money
    else: #如果没有的话
        data_dict[record.date] = record.money  #这就是没有日期的,在其新的日期下赋了一个money的值

# print(data_dict) 得到了字典,{日期:金额}

# 5,通过PyEcharts进行图形绘制
bar = Bar(init_opts=InitOpts(theme=ThemeType.LIGHT)) #构建类对象

bar.add_xaxis(list(data_dict.keys()))
bar.add_yaxis("销售额",list(data_dict.values()),label_opts=LabelOpts(is_show=False))
bar.set_global_opts(
    title_opts=TitleOpts(title="每日销售额")
)
bar.render("每日销售额.html")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第一章Python基本 6 一Python 简介 6 (一) Python 定义 6 (二) Python程序的执行方式 7 (三)Linux常用命令 7 (四)执行过程 8 (五)解释器类型 8 (六)调试 9 二 数据基本运算 9 (一)pycharm常用快捷键(编译器) 9 (二) 函数 函数名(参数) 10 (三)变量 存储数据 11 (四)del 语句 14 (五)核心数据类型 14 (六)数据类型转换 16 (七)运算符 17 三 语句 23 (一)行 23 (二)pass 语句 23 (三)选择语句 24 (四)循环语句 25 (五)跳转语句 30 (六)print相关函数 30 四 容器类型 30 (一)通用操作 30 (二)字符串 str(不可变序列+字符编码值) 33 (二) 列表 list (预留空间+可变序列+储存变量) 35 (四) 元组 tuple(按需分配+不可变序列+存储变量) 44 (五) 字典 dict (按键取值+可变散列+存储键值对) 46 (六) 集合 set (去重复/数学运算+存储键+可变散列) 52 (七)固定集合 frozenset 54 五 函数 function(小而精) 55 (一)pycharm相关设置 55 (二)定义 55 (三)作用 56 (四)定义函数 56 (五)调用函数 56 (六)返回值 57 (七)可变/不可变类型在传参时的区别 58 (八)函数参数 59 六 作用域LEGB 66 (一)变量名的查找规则 66 (二)局部变量 66 (三)全局变量 66 (四)global 语句 67 (五)nonlocal 语句(外部嵌套) 67 第二章 面向对象 Object Oriented 68 一 概述 68 (一)面向过程 68 (二)面向对象 68 二 类和对象 69 (一)语法 70 (二)实例成员 72 (三)类成员 75 (四)静态方法 76 (总结)类和对象 77 三 三大特征 78 (总结)三大特征 78 (一)封装(按需求分,按行为分) 78 (二)继承(抽象 -> 统一 -> 隔离) 86 (三) 多态 90 四 设计原则 95 (总结)设计原则 95 (一)开-闭原则(目标、总的指导思想,增加不改变原代码) 95 (二)类的单一职责(一个类的定义) 96 (三)依赖倒置(依赖抽象) 96 (四)组合复用原则(复用的最佳实践) 96 (五)里氏替换(扩展重写,继承后的重写,指导继承的设计) 96 (六)迪米特法则(用父类减少传递数据量,类与类交互的原则) 97 第三章 模块包+函数式编程 98 通用:快捷键 98 一 模块 Module 98 (一)定义: 包含一系列数据、函数、类的文件,通常以.py结尾。 99 (二)作用 99 (三)导入 99 (四) 模块变量 100 (五)加载过程 100 (六)分类 101 (七)搜索顺序 102 二 包package 102 (一)定义:将模块以文件夹的形式进行分组管理。 102 (二)作用:让一些相关的模块组织在一起,使逻辑结构更加清晰。 102 (三)导入 102 (四) 搜索顺序 103 三 异常处理Error 104 (一)异常 104 (二)处理 105 (三)raise 语句 106 (四)自定义异常:为了快速传递错误信息 108 四 迭代 108 (一)可迭代对象iterable 109 (二) 迭代器对象iterator 110 五 生成器generator 113 (一)生成器函数 114 (二)内置生成器 116 (三)生成器表达式 116 六 函数式编程 118 (一)函数作为参数 119 (二)内置高阶函数 122 (三) 函数作为返回值 124

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵唯一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值