【Python】狂肝两万字带你学会——类与对象

news2024/12/27 13:28:32

目录

01-初始对象

生活中的数据组织

程序中的数据组织​编辑

使用对象组织数据

总结01

02-类的成员方法

类的定义和使用

成员变量和成员方法 

成员方法的定义语法

 注意事项

成员方法——代码演示 

总结02

03-类和对象

现实世界的事物和类

类和对象

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

在现实中,生产事物 ​

总结03 

04-构造方法

属性(成员变量)的赋值 

构造方法:

总结04: 

        练习:学生信息录入

【参考代码】 

 05-魔术方法

__ str __        字符串方法

__lt__            小于符号比较方法 

__ le __         小于等于比较符号方法

__eq__          比较运算符实现方法

总结05

06-封装

封装

对用户隐藏的属性和行为

私有成员

禁止使用私用成员​

 总结06

课后练习:设计带有所有成员的手机

继承

07-继承的基础语法

继承的引出

单继承​​​​​

多继承 

总结07

08-复写父类成员和调用父类成员

调用父类的同名成员

总结08

09-变量的类型注解

为什么需要类型注释

类型注解

类型注解的语法

演示代码 

总结09:

10-函数和方法类型注解

形参注解 

返回值注释

总结10

11-Union联合类型注解

Union类型:定义联合类型注解

总结11

12-多态

​抽象类

 配合多态完成

 总结12

13-【面向对象】例题讲解

数据分析案例 

需求分析

【1】数据的读取和封装

【2】-数据计算

【3】-可视化开发


作者🕵️‍♂️:让机器理解语言か

专栏🎇:Python

描述🎨:人生苦短,我用Python!

寄语💓:🐾没有白走的路,每一步都算数!🐾 

前言:

本文参考B站黑马程序员Python课程。大家阅读时有什么不理解的地方可以看一下视频哦!B站黑马py-类与对象 

01-初始对象

学习目标:理解使用对象完成数据组织的思路

首先,我们为什么要引入对象呢? 让我们发现痛点!!

生活中的数据组织

 没有统一格式/规范,所以数据组织起来非常混乱,所以将白纸改为登记表,规范化填写,信息简洁明了,容易对数据进行组织管理。

 在程序中可以使用字典,字符串和列表来维护学生的信息,但格式的多种多样,就造成了组织的混乱和不统一。

程序中的数据组织

 使用变量记录数据太乱了。我们希望数据的组织可以达到简洁统一,如果在程序中可以像生活中一样

  • 可以设计表格
  • 可以将设计的表格打印出来
  • 可以将打印好的表格供人填写内容

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

那么好,我们引入对象,使用对象来组织数据!接下来看一下在程序中如何使用对象。

使用对象组织数据

  • 设计表格,称之为:设计类(class) 
  • 打印表格,称之为:创建对象 
  • 填写表格,称之为:对象属性赋值

if __name__ == '__main__':
    # 1.设计一个类(类比生活中:设计一张登记表)
    class  Student:
        name = None        # 记录学生姓名
        gender = None        # 记录学生性别
        nationality = None        # 记录学生国籍
        native_place = None  # 记录学生籍贯
        age = None        # 记录学生年龄


    # 2.创建一个对象(类比生活中:打印一张登记表)
    stu_1 = Student()
    # 3.对象属性进行赋值(类比生活中:填写表单)
    stu_1.name = "林军杰"
    stu_1.gender = "男"
    stu_1.nationality = "中国"
    stu_1.native_place = "山东省"
    stu_1.age = 31
    # 4.获取对象中记录的信息
    print(stu_1.name )  # 林军杰
    print(stu_1.gender) # 男
    print(stu_1.nationality)  # 中国
    print(stu_1.native_place) # 山东省

总结01:

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

  • 设计表格,称之为:设计类(class) 
  • 打印表格,称之为:创建对象 
  • 填写表格,称之为:对象属性赋值

02-类的成员方法

学习目标

  1. 掌握类的定义和使用语法
  2. 掌握成员方法的使用
  3. 掌握self关键字的作用

类的定义和使用

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

类的组成:属性+行为
类的组成:属性+行为

现在我们来看看类的使用语法: 

class 类名称:
	类的属性
	类的行为

●class是关键字, 表示要定义类了
●类的属性:定义在类中的变量(成员变量)
● 类的行为:定义在类中的函数(成员方法)
创建类对象的语法

对象 = 类名称()

成员变量和成员方法 


 可以看出,类中:

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

注意:类内部的函数叫(成员)方法,不叫函数。

成员方法的定义语法

在类中定义成员方法和定义函数基本一致,但仍有细微区别:

def 方法名(self,形参1, ......,形参N):
    方法体

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

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

  • 它用来表示类对象自身的意思
  • 当我们使用类对象调用方法的是,self会自动被python传入
  • 在方法内部,想要访问类的成员变量,必须使用self。例如下面代码中的在say_hi( )方法中的访问类的成员变量name:se1f.name
class student:
    name = None#学生的姓名
    age = None# 学生的年龄
    def say_hi(se1f):
        print(f"Hi大家好,我是{se1f.name} ")
stu = student()
stu.name ="周杰轮"
stu.say_hi()#输出:Hi大家好,我是周杰轮

 注意事项

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

if __name__ == '__main__':
    # 1.设计一个类(类比生活中:设计一张登记表)
    class  Student:
        name = None        # 记录学生姓名
        def say_hi(self):        # 访问类的成员变量需要self.name
            print("hi!")
        def say_hi2(self,msg):
            print(f"hi!,{msg}")  # 访问外部变量不需要self.msg

stu1 = Student()
stu1.say_hi()                 #调用的时候无需传参
stu1.say_hi2("很高兴认识你!") #调用的时候,需要传msg参数
# hi!
# hi!,很高兴认识你!

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

成员方法——代码演示 

class  Student:
    name = None        # 记录学生姓名
    def say_hi(self):
        print("我是",self.name)
    def say_hi2(self,msg):
        print(f"我的口头禅是:{msg}")  # 访问外部变量不需要self.msg
if __name__ == '__main__':
    s1 = Student()
    s1.name = "周杰伦"
    s1.say_hi()              # 我是 周杰伦
    s1.say_hi2("哎哟不错哟")  # 我的口头禅是:哎哟不错哟

    s2 = Student()
    s2.name = "小猪佩奇"
    s2.say_hi()              # 我是 小猪佩奇
    s2.say_hi2("吼吼吼!!!")# 我的口头禅是:吼吼吼!!!

总结02:

1.类是由哪两部分组成呢?

  • 类的属性,称之为:成员变量
  • 类的行为,称之为:成员方法

注意:函数是写在类外的,定义在类内部,我们都称之为方法哦!
2.类和成员方法的定义语法

class类名称:
    成员变量
    
    def成员方法(self,参数列表)∶
        成员方法体
对象=类名称()

3.self的作用

  • 表示类对象本身的意思
  • 只有通过self,成员方法才能访问类的成员变量
  • self出现在形参列表中,但是不占用参数位置,无需理会 

03-类和对象

学习目标

1.掌握使用类描述现实世界事物的思想
2.掌握类和对象的关系
3.理解什么是面向对象

现实世界的事物和类

现实事物的两大特征:

  • 属性
  • 行为

在这里插入图片描述

现实世界的事物也有属性和行为,类也有属性和行为。
使用程序中的类,可以完美的描述现实世界的事物

类和对象

基于类创建对象的语法:对象名=类名称()
为什么非要创建对象才能使用呢?
类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作,这就是我们所说的:面向对象编程!!!!

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

在现实中,生产事物 

基于类创建对象

面向对象的核心:设计类——就是让类干活!
在这里插入图片描述
下面代码有声音欧 耳机党小心!!!!!

if __name__ == '__main__':
    # 设计一个闹钟类
    class Clock:
        id = None# 序列化
        price = None # 价格

        def ring(self):
            import winsound
            winsound.Beep(2000,3000)


    # 构建2个闹钟对象并让其工作
    clock1 = Clock()
    clock1.id = "003032"
    clock1.price = 19.99
    print(f"闹钟ID: {clock1.id}, 价格: {clock1.price}")
    clock1.ring()
    #######################################
    clock2 = Clock()
    clock2.id = "003033"
    clock2.price = 21.99
    print(f"闹钟ID: {clock2.id}, 价格: {clock2.price}")
    clock2.ring()
# 闹钟ID: 003032, 价格: 19.99
# 闹钟ID: 003033, 价格: 21.99

总结03 

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

  • 属性
  • 行为

类也可以包含属性和行为,所以使用类描述现实世界事物是非常合适的
2.类和对象的关系是什么?
类是程序中的设计图纸”
对象是基于图纸生产的具体实体
3.什么是面向对象编程?
面向对象编程就是,使用对象进行编程。
即。设计类,基于类去创建对象,并使用对象来完成具体的工作
 

04-构造方法

学习目标:

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

属性(成员变量)的赋值 

class Student:
    name = None#名称
    age = None#年龄
    tel = None#手机号
student1 = Student()
student1.name ="周杰轮"
student1.age = 31
student1.tel = "18012340000"
student2 = Student()
student2.name ="周杰轮"
student2.age = 31
student2.tel = "18012340000"

上面代码中,为对象的属性赋值需要依次进行,略显繁琐。有没有更加高效的方式,能够一行代码就完成呢?
思考: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("Student类创建了一个类对象")
if __name__ == '__main__':
    stu = Student("周杰轮",31, "18500006666")

当写了构造函数后,成员变量的定义是可以省略的:

class Student:
    def __init__(self, name,age, tel):
        self.name = name
        self.age = age
        self.tel = tel
        print("Student类创建了一个类对象")
if __name__ == '__main__':
    stu = Student("周杰轮",31, "18500006666")

注意事项📌:

  1. 重要的事情说三遍,构造方法名称:__init__ __init__ __init__,千万不要忘记init前后都有2个下划线
  2. 构造方法也是成员方法,不要忘记在参数列表中提供:self。这是因为︰变量是定义在构造方法内部,如果要成为成员变量﹐需要用self来表示。
  3. ❗❗❗构造方法内定义成员变量,需要使用self关键字
class Student:
    def __init__(self, name,age, tel): 
        self.name = name  # 在构造方法内定义成员变量,需要使用self关键字
        self.age = age
        self.tel = tel
        print("Student类创建了一个类对象")
if __name__ == '__main__':
    stu = Student("周杰轮",31, "18500006666")
    print(stu.name)
    print(stu.age)
    print(stu.tel)
# Student类创建了一个类对象
# 周杰轮
# 31
# 18500006666

总结04: 

1.构造方法的名称是︰
_init__,注意init前后的2个下划线符号

2.构造方法的作用:

  • 构建类对象的时候会自动运行
  • 构建类对象的传参会传递给构造方法,借此特性可以给成员变量赋

3.注意事项:

  • 构造方法不要忘记self关键字
  • 在方法内使用成员变量需要使用self

练习:学生信息录入

【参考代码】 

class Student:
    def __init__(self, name, age, address):
        self.name = name  # 在构造方法内定义成员变量,需要使用self关键字
        self.age = age
        self.address = address


if __name__ == '__main__':
    for i in range(1,11):
        print(f"当前录入第{i}位学生信息,总共需录入10位学生信息")
        name = input("请输入学生姓名:")
        age = input("请输入学生年龄:")
        address = input("请输入学生地址:")
        stu = Student(name, age, address)
        print(f"学生1信息录入完成,信息为:【学生姓名:{stu.name},年龄:{stu.age},地址:{stu.address}】")

 05-魔术方法

学习目标       

1.掌握几种常用的类内置方法

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

 魔术方法非常多,我们学习几个常见的即可

__ str __        字符串方法

内存地址没有多大作用,当类对象需要被转换为字符串之时,我们可以通过_str_方法,控制类转换为字符串的行为。 

  • 方法名::__str__
  • 返回值:字符串
  • 内容:自行定义
class Student:
    def __init__(self, name, age):
        self.name = name# 学生姓名
        self.age = age# 学生年龄
    # __ str__魔术方法
    def __str__(self):
        return f"Student类对象,name:{self.name}, age:{self.age}"
stu = Student("周杰轮",31)
print(stu)
print(str(stu))
#Student类对象,name:周杰轮, age:31
#Student类对象,name:周杰轮, age:31

__lt__        小于符号比较方法 

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

 

class Student:
    def __init__(self, name, age):
        self.name = name# 学生姓名
        self.age = age# 学生年龄
    # __ str__魔术方法
    def __str__(self):
        return f"Student类对象,name:{self.name}, age:{self.age}"

    #__lt__魔术方法.
    def __lt__(self,other):
        return self.age < other.age

stu1 = Student("周杰轮",31)
stu2 = Student("林俊杰",34)
print(stu1<stu2) # True
print(stu1>stu2) # False

__ le __      小于等于比较符号方法

魔术方法:_le_可用于:<=、>=两种比较运算符上。 

__eq__, 比较运算符实现方法

  • 不实现_eq_方法,对象之间可以比较,但是是比较内存地址,也即是:不同对象==  比较一定是False结果。
  • 实现了_eq_方法,就可以按照自己的想法来决定2个对象是否相等了。

总结05:

06-封装

面向对象的三大特性
面向对象编程,是许多编程语言都支持的一种编程思想。
简单理解是:基于模板(类)去创建实体(对象) ,使用对象完成功能开发。
面向对象包含3大主要特性:
➢封装
➢继承
➢多态

封装

封装表示的是,将现实世界事物的属性行为封装到类中,描述为:成员变量成员方法,从而完成程序对现实世界事物的描述。

对用户隐藏的属性和行为

 现实世界中的事物,有属性和行为。

但是不代表这些属性和行为都是开放给用户使用的。

所以会有平果越狱和安卓root的行为,我们想获取他不想让我们看到的东西。

私有成员

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

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

  • 私有成员变量
  • 私有成员方法

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

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

即可完成私有成员的设置

禁止使用私用成员

私有成员无法被类对象使用,但是可以被其它的成员使用

class Phone:
    __current_voltage = 0.5
    # 当前手机运行电压
    def __keep_single_core(self):
        print("让CPU以单核模式运行")


    def call_by_5g(self):
        if self.__current_voltage >= 1:
            print("5g通话已开启")
        else:
            self.__keep_single_core()  # 调用不公开的私有成员变量
            print("电量不足,无法使用5g通话,并已设置为单核运行进行省电。")

phone = Phone()
phone.call_by_5g() 
# 让CPU以单核模式运行
# 电量不足,无法使用5g通话,并已设置为单核运行进行省电。

A:私有成员的定义我们已经了解了,但是:它有什么实际的意义吗?
Q:在类中提供仅供内部使用的属性和方法﹐而不对外开放(类对象无法使用)

 总结06:

1.封装的概念是指?
将现实世界事物在类中描述为属性和方法,即为封装。

2.什么是私有成员?为什么需要私有成员?
现实事物有部分属性和行为是不公开对使用者开放的。

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

3.如何定义私有成员?
成员变量和成员方法的命名均以  __  作为开头即可

4.私有成员的访问限制?

  • 类对象无法访问  私有成员
  • 类中的其它成员可以访问  私有成员

课后练习:设计带有所有成员的手机

if __name__ == '__main__':
    class Phone:
        # 提供私有成员变量:__ is_ 5g_ enabZe
        __is_5g_enable = False
        # 5g状态
        # 提供私有成员方法: __ check_ 5g()
        def __check_5g(self):
            if self.__is_5g_enable:
                print("5g开启")
            else:
                print("5g关闭,使用4g网络|")
        # 提供公开成员方法: call_by_5g()
        def call_by_5g(self):
            self.__check_5g()
            print("正在通话中")
    phone = Phone()
    phone.call_by_5g()

    '''
    5g关闭,使用4g网络|
    正在通话中
    '''

继承

分两节来讲:

  • 07——继承的基础语法  
  • 08——复写父类成员和调用父类成员

07-继承的基础语法

学习目标

1.理解继承的概念
2.掌握继承的使用方式
3.掌握pass关键字的作用

继承的引出 

如果你是设计师,你会如何选择?
1.每一代新款手机,都从零开始出设计图

2.基于老款的设计图,修修改改

想必大多数人都会选择第二种做法

在程序中也有相同的逻辑

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

单继承:​​​​​

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

class 子类名(父类名):
	类内容体  # 新功能

代码演示:

class Phone:
    IMEI = None
    producer = "HM"
    def call_by_4g(self):
        print("4g通话")
class Phone2023(Phone):
    face_id = "10001"
    def call_by_5g(self):
        print("2023年功能:5g通话")
phone = Phone2023()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
# HM
# 4g通话
# 2023年功能:5g通话

 多继承 

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


  

在这里插入图片描述

class 类名(父类1,父类2,......,父类N):
    类内容体
class Phone:
    IMEI = None#序列号
    producer = "ITCAST"#厂商
    def call_by_5g(self):
        print("5g通话")
class NFCReader:
    nfc_type ="第五代"
    producer = "HM"
    def read_card(self):
        print("读取NFC卡")
    def write_card(self):
        print("写入NFC卡")
class Remotecontrol :
    rc_type ="红外遥控"
    def control(self):
        print("红外遥控开启")
class MyPhone(Phone, NFCReader, Remotecontrol):
    pass
phone = MyPhone()
phone.call_by_5g()# 5g通话
phone.control()   # 红外遥控开启
print(phone.producer) # ITCAST  按照传入父类顺序来,只输出第一个

 其中pass关键字是补全语法。让语法补充,避免错误。

当输出同名属性时,以传入第一个具有该属性的父类为准

总结07

1.什么是继承?
继承就是一个类,继承另外一个类的成员变量和成员方法
语法:

class 类(父类[,父类2,......,父类N])∶
    类内容体

子类构建的类对象,可以

  • 有自己的成员变量和成员方法
  • 使用父类的成员变量和成员方法

2.单继承和多继承
单继承:一个类继承另一个类
多继承:一个类继承多个类,按照顺序从左向右依次继承
多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承
3.pass关键字的作用是什么
pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思

08-复写父类成员和调用父类成员

学习目标
1.掌握复写父类成员的语法
2.掌握如何在子类中调用父类成员

子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。即:在子类中重新定义同名的属性或方法即可。’复写‘可以理解为’修改‘。

class Phone:
    IMEI = None
    # 序列号
    producer = "ITCAST"  # 厂商
    def call_by_5g(se1f):
        print("父类的5g通话")


class MyPhone(Phone):
    proucer = "ITHEIMA"        # 复写父类属性
    def call_by_5g(se1f):      # 复写父类方法
        print("开启CPU单核模式,确保通话的时候省电")
        print("使用5g网络进行通话")
        print("关闭CPU单核模式,确保性能")


phone = MyPhone()
print(phone.proucer)
phone.call_by_5g()

'''
ITHEIMA
开启CPU单核模式,确保通话的时候省电
使用5g网络进行通话
关闭CPU单核模式,确保性能
'''

调用父类的同名成员

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

方式1:

  • 调用父类成员

使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2:

  • 使用super()调用父类成员

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

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

class Phone:
    IMEI = None
    # 序列号
    producer = "ITCAST"  # 厂商
    def call_by_5g(se1f):
        print("使用5g网络进行通话")


class MyPhone(Phone):
    proucer = "ITHEIMA"        # 复写父类属性
    def call_by_5g(self):      # 复写父类方法
        print("开启CPU单核模式,确保通话的时候省电")
        #方式1
        print(f"父类的厂商是: {Phone.producer}")
        Phone.call_by_5g(self)  # 这里的参数随便填一个都行,就是不要和子类的方法参数self相同
        #方式2
        print(f"父类的厂商是: {super().producer}")  # super只适制于单继承,或者多继承没有重复名的情况,当遇到遇到多个父类有重复名时,优先级跟继承的一样,优先取左边的
        super().call_by_5g() 
        print("关闭CPU单核模式,确保性能")


phone = MyPhone()
print(phone.proucer)
phone.call_by_5g()

'''
ITHEIMA
开启CPU单核模式,确保通话的时候省电
父类的厂商是: ITCAST
使用5g网络进行通话
父类的厂商是: ITCAST
使用5g网络进行通话
关闭CPU单核模式,确保性能
'''

总结08

1.复写表示:
对父类的成员属性或成员方法进行重新定义
2.复写的语法:
在子类中重新实现同名成员方法或成员属性即可
3.在子类中,如何调用父类成员

方式1:

  • 调用父类成员

使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2:

  • 使用super()调用父类成员

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

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

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

09-变量的类型注解

学习目标
1.理解为什么使用类型注解
2.掌握变量的类型注解语法

为什么需要类型注释

在PyCharm中编写代码,我们经常能够见到如下提示: 

 自动提示可用方法

思考:为什么PyCharm工具能够做到这一点?它是如何知道这个对象有append方法?
因为︰PyCharm确定这个对象,是List类型

同样,我们换一份代码:
定义一个函数func,接收一个参数data你会发现,PyCharm不会在做出任何提示了


思考,为什么PyCharm工具无法提示了?
因为︰PyCharn不确定这个对象是什么类型

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

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

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

类型注解

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

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

  • 帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示
  • 帮助开发者自身对变量进行类型注释

支持:

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

类型注解的语法

为变量设置类型注解

基础语法:变量:类型
 


注意:

  • 元组类型设置类型详细注解,需要将每一个元素都标记出来
  • 字典类型设置类型详细注解,需要2个类型,第一个是key,第二个是value

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

语法:# type:类型

 

 为变量设置注解,显示的变量定义,一般无需注解:

 

如上图,就算不写注解,也明确的知晓变量的类型 

 一般,无法直接看出变量类型之时会添加变量的类型注解

类型注解主要功能在于:

  • 帮助第三方IDE工具(如Pycnarm) 
  • 帮助开发者自身对变量进行类型注释(备注)

并不会真正的对类型做验证和判断。
也就是,类型注解仅仅是提示性的,不是决定性

var_1: int = "itheima"
var_2: str = 123

如图代码,虽然标注类型错误了,但是不会报错的哦。

演示代码 

# 基础数据类型注解
var_1: int = 10
var_2: str = "itheima"
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 = {"itheima": 666}

# 在注释中进行类型注解
my_list= [1,2, 3] #type:list
my_tuple= ("itheima", 666, True)#type:tuple[str, int, bool]

# 类型注解的限制
var_7: str = 10 # 标错了,但不会报错

总结09:

1.什么是类型注解,有什么作用?
在代码中涉及数据交互之时,对数据类型进行显式的说明,可以帮助:.

  • PyCharm等开发工具对代码做类型推断协助做代码提示
  • 开发者自身做类型的备注

2.类型注解支持:

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

3.变量的类型注解语法

  • 语法1︰变量:类型
  • 语法2:在注释中,# type:类型

4.注意事项

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

10-函数和方法类型注解

学习目标
1.掌握为函数(方法)形参进行类型注解
2.掌握为函数(方法)返回值进行类型注解

形参注解
 

如图所示:

  • 在编写函数(方法),使用形参data的时候,工具没有任何提示
  • 在调用函数(方法),传入参数的时候,工具无法提示参数类型 

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

函数和方法的形参类型注解

语法:

def 函数方法名(形参名:类型,形参名:类型,......):
	pass

返回值注释

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

def 函数方法名(形参:类型.......形参:类型)-> 返回值类型:
    pass

类型注解只是提示性的,并非决定性的。

整理会有警告但不会报错,可以正常运行,输出结果为1。

总结10

1.函数(方法)可以为哪里添加注解?

  • 形参的类型注解
  • 返回值的类型注解

2.函数(方法)的类型注解语法?

def 函数方法名(形参:类型,......,形参:类型)->返回值类型
    pass

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

11-Union联合类型注解

学习目标
1.理解Union类型
2.掌握使用Union进行联合类型注解

Union类型:定义联合类型注解

语法:Union[类型,类型…]

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

总结11

1.什么是Union类型?
使用Union可以定义联合类型注解
2.Union的使用方式

  • 导包: from typing import Union
  • 使用: Union[类型,.......类型]

12-多态

学习目标
1.理解多态的概念
2.理解抽象类(接口)的编程思想

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

同样的行为(函数),传入不同的对象,得到不同的状态

多态常作用在继承关系上.
比如

  • 函数(方法)形参声明接收父类对象。
  • 实际传入父类的子类对象进行工作

即:

  • 以父类做定义声明
  • 以子类做实际工作
  • 用以获得同一行为,不同状态


抽象类

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

 这种设计的含义是:

  • 父类用来确定有哪些方法
  • 具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也可以称之为接口)
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法

为什么要使用抽象类呢?


提出标准后,不同的厂家各自实现标准的要求。
抽象类可以理解成标准框架;提出的要求)!什么意思?就是告诉人们,我有这个功能,自己(父类)不实现,但是他的子类必须实现,要不这个要求就是没有实现。

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

 

 AC是一个标准(用来做顶层设计),真正工作的是AC的子类。

 

例如,AC的cool_wind()是一个标准,Midea_AC和GREE_AC的cool_wind()就是实现标准的过程,虽然都是实现了标准,但实现标准的过程可能不同(多态),如美的空调核心制冷科技和格力空调变频省电制冷。

 配合多态完成

  • 抽象的父类设计(设计标准)
  • 具体的子类实现(实现标准)

 

 总结12

1.什么是多态?
多态指的是,同一个行为,使用不同的对象获得不同的状态。
如,定义函数(方法),通过类型注解声明需要父类对象,实际传入子类对象进行工作,从而获得不同的工作状态
2.什么是抽象类(接口)
包含抽象方法的类,称之为抽象类。抽象方法是指:没有具体实现的方法(pass)称之为抽象方法
3.抽象类的作用
多用于做顶层设计(设计标准),以便子类做具体实现。
也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法
并配合多态使用,获得不同的工作状态。

13-【面向对象】例题讲解

学习目标
1.使用面向对象思想完成数据读取和处理
2.基于面向对象思想重新认知第三方库使用(PyEcharts) 

链接:https://pan.baidu.com/s/1Up95mikhWrB_ubBE_uxToA
提取码:qli8

大家先下载数据再测试案例嗷!

数据分析案例 

某公司,有2份数据文件,现需要对其进行分析处理,计算每日的销售额并以柱状图表的形式进行展示。

数据内容 

1月份数据是普通文本,使用逗号分割数据记录,从前到后分别是(日期,订单id,销售额,销售省份)

2月份数据是JSON数据,同样包含(日期,订单id,销售额,销售省份)

需求分析


作为面向对象的程序员,我们全程将使用面向对象的思想来进行任务的开发

面向对象,数据分析案例,主业务逻辑代码实现步骤:

  1. 设计一个类,可以完成数据的封装
  2. 设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功的
  3. 读取文件,生产数据对象
  4. 进行数据需求的逻辑计算(计算每一天的销售额)
  5. 通过PyEcharts进行图形绘制

【1】数据的读取和封装

data_ define.py

# 数据定义的类
class Record:
    #定义4个成员变量
    def __init__(self,data,order_id,money,provine):
        self.date = data  #订单日期
        self.order_id = order_id#订单ID
        self.money = money#订单金额
        self.provine = provine#订单省份
    def __str__(self):    # 字符串方法:将地址转为实际内容
        return (f"{self.date},{self.order_id},{self.money},{self.provine}")

file_ define.py

# 文件相关的类定义
import json

from data_define import Record

class FileReader:
    def read_data(self)-> list[Record]:
# 读取文件的数据,读到的每一条数据都转换为Record对象,将它们都封装到List内返回即可
        pass

class TextFileReader(FileReader):
    def __init__(self,path):
        self.path = path
    def read_data(self):
        f = open(self.path,"r",encoding="UTF-8")
        record_list = []
        for line in f.readlines():
            line = line.strip()          # 消除\n
            data_list = line.split(",")  # 分割数据
            record= Record(data_list[0],data_list[1],int (data_list[2]),data_list[3]) 
            record_list.append(record)
        f.close()
        return record_list #list[Record]

class JsonFileReader(FileReader):
    def __init__(self,path):
        self.path = path
    def read_data(self) :
        f = open(self.path,"r",encoding="UTF-8")
        record_list = []
        for line in f.readlines():
            data_dict = json.loads(line)    # 转为字典形式
            record = Record(data_dict["date"],data_dict["order_id"],int(data_dict["money"]),data_dict["province"])
            record_list.append(record)#list[Record]
        f.close()
        return record_list



if __name__ == '__main__':    # 被其他文件调包时这里不会执行
     text_file_reader = TextFileReader("2011年1月销售数据.txt")  # 这里的参数是你当前文件的路径
     json_file_reader = JsonFileReader("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)

【2】-数据计算

main.py

from file_define import FileReader,TextFileReader,JsonFileReader
from data_define import Record

text_file_reader = TextFileReader("2011年1月销售数据.txt")
json_file_reader = JsonFileReader("2011年2月销售数据JSON.txt")

jan_data = text_file_reader.read_data() #list[Record]
feb_data = json_file_reader.read_data()#list[Record]

all_data = jan_data+feb_data #list[Record]

data_dict = {}
for record in all_data:
    if record.date in data_dict.keys():
        # 当前日期已经有记录了,所以和老记录做累加即可
        data_dict[record.date] += record. money
    else:
        data_dict[record.date] = record. money
print(data_dict)

【3】-可视化开发

mian.py 

from file_define import FileReader,TextFileReader,JsonFileReader
from data_define import Record
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType
from pyecharts.options import TitleOpts

text_file_reader = TextFileReader("2011年1月销售数据.txt")
json_file_reader = JsonFileReader("2011年2月销售数据JSON.txt")

jan_data = text_file_reader.read_data() #list[Record]
feb_data = json_file_reader.read_data()#list[Record]

all_data = jan_data+feb_data #list[Record]

data_dict = {}
for record in all_data:
    if record.date in data_dict.keys():
        # 当前日期已经有记录了,所以和老记录做累加即可
        data_dict[record.date] += record. money
    else:
        data_dict[record.date] = record. money

bar = Bar()

bar.add_xaxis(list(data_dict.keys()))
bar.add_yaxis("销售额",list(data_dict.values()))
bar.set_global_opts(
    title_opts = TitleOpts(title="每日销售额")
)
bar.render("每日销售额柱状图.html")

 对上面的表格修改一下,去掉数据值,颜色改为蓝色。

main.py

from file_define import FileReader,TextFileReader,JsonFileReader
from data_define import Record
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType
from pyecharts.options import TitleOpts
from pyecharts.options import LabelOpts
from pyecharts.options import InitOpts
text_file_reader = TextFileReader("2011年1月销售数据.txt")
json_file_reader = JsonFileReader("2011年2月销售数据JSON.txt")

jan_data = text_file_reader.read_data() #list[Record]
feb_data = json_file_reader.read_data()#list[Record]

all_data = jan_data+feb_data #list[Record]

data_dict = {}
for record in all_data:
    if record.date in data_dict.keys():
        # 当前日期已经有记录了,所以和老记录做累加即可
        data_dict[record.date] += record. money
    else:
        data_dict[record.date] = record. money

bar = Bar(init_opts=InitOpts(theme=ThemeType.LIGHT)) # 在Bar类里传入的参数会到自动构造方法里

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")

        OK~~~,【类与对象】已经完结啦,希望大家可以和我一样收获满满!让我们一起努力。朝着美好的未来前进吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/479379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 9.0 原生SystemUI下拉通知栏每条通知默认展开

1.前言 在9.0的系统rom原生开发中,在产品对SystemUI下拉通知栏做定制的时候,在下拉状态栏的时候,通知栏中 最后一条通知默认是收缩的 点击按钮 就会展开 原生系统systemui就是如此,为了更美观 所以要求最后一条通知也默认展开,显得更美观 最终效果图: 2.原生SystemUI下拉通…

网络通信原理

网络通信原理目录 1.网络通信基础1.1 IP地址1.2 端口号 2. 通信协议2.1 协议简介2.1 协议分层 3. 封装和分用 1.网络通信基础 &#x1f604;网络通信的目的是网络数据传输&#xff0c;是主机的不同进程间&#xff0c;基于网络实现的数据传输。那么&#xff0c;首先我们应该先弄…

Java实现调用外部程序

Java实现调用外部程序 Java库Runtime类与ProcessBuilder类参数传递执行结果Runtime类的使用ProcessBuilder类的使用无参数调用简单参数调用复杂参数调用 Apache Commons Exec库使用步骤介绍使用实例 Java库 在Java中&#xff0c;可以通过Runtime类或ProcessBuilder类来实现调用…

看看人家的MyBatis批量插入数据优化,从120s到2.5s,那叫一个优雅!

粗略的实验 最后 最近在压测一批接口的时候&#xff0c;我发现接口处理速度比我们预期的要慢。这让我感到有点奇怪&#xff0c;因为我们之前已经对这些接口进行了优化。但是&#xff0c;当我们进行排查时&#xff0c;发现问题出在数据库批量保存这块。 我们的项目使用了 myb…

开源小项目ChatGPT-website已获得100+star,我都干了什么

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

微信小程序学习实录1(wxml文档、引入weui、双向数据绑定、提交表单到后端)

微信小程序学习实录 一、wxml文档二、新建页面快捷方式三、微信小程序引入weui四、双向数据绑定1.wxml渲染层2.js逻辑层 提交表单到后端五、微信小程序跳转到H5 一、wxml文档 <!-- index.wxml --> <view><!-- 数据绑定 --><view><text>{{name}}…

蛋白质界的 ChatGPT:AlphaFold2 论文必备知识,不会有人还不知道吧

你知道 AlphaFold2 吗&#xff1f;它真正解决了蛋白质三维结构预测的算法困境&#xff0c;堪称蛋白质界的 chat-GPT4&#xff0c;甚至它的意义不是 chat-GPT4 所能够匹敌的。它为世界疾病治疗药物开发以及探究生物生命之谜提供了通向天神的一条道路&#xff0c;未来是生物的世纪…

Java 基础入门篇(二)—— Java 基础语法

文章目录 一、注释二、字面量三、变量3.1 变量概述3.2 变量在计算机中的底层原理 四、数据类型五、关键字、标志符六、类型转换6.1 自动类型转换6.2 表达式的自动类型转换6.3 强制类型转换 七、运算符7.1 基本算数运算符7.2 符号做连接符7.3 自增自减运算符7.4 赋值运算符7.5 …

Java 基础入门篇(五)—— 面向对象编程

文章目录 一、面向对象的思想二、类的定义与对象的创建三、对象内存分配情况 ★ 3.1 两个对象的内存图3.2 两个变量指向同一个对象内存图 四、构造器4.1 构造器的格式与分类4.2 构造器的调用 五、 this 关键字六、封装七、标准JavaBean补充&#xff1a;局部变量和成员变量的区别…

Java 基础入门篇(六)—— String 类详解

文章目录 一、String 类概述二、String 创建对象的方式2.1 创建对象的两种方式2.2 面试&#xff1a;两种方式的区别 ★2.3 常见面试题 ★ 三、String 类常用方法3.1 字符串内容比较3.2 常用 API&#xff1a;遍历、截取、替换、分割 一、String 类概述 java.lang.String 类代表…

Java 基础入门篇(四)—— 方法的重载与参数传递机制

文章目录 一、方法的定义二、方法的参数传递机制 ★2.1 基本类型的参数传递2.2 引用类型的参数传递 三、方法重载 一、方法的定义 方法的作用&#xff1a;封装一段代码的语法结构&#xff0c;可以被重复调用&#xff0c;以此提高代码的复用性&#xff0c;提高开发效率&#xf…

【VsCode远程开发】Windows SSH远程连接Linux服务器 - 无公网IP内网穿透

文章目录 前言视频教程1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 转…

Java 基础进阶篇(一)—— static 静态关键字与单例模式

文章目录 一、static 静态关键字1.1 静态成员变量与实例成员变量1.2 静态成员方法与实例成员方法1.3 static 访问注意事项1.4 内存使用情况 二、工具类三、代码块四、单例模式4.1 饿汉单例4.2 懒汉单例 一、static 静态关键字 static&#xff1a;代表静态的意思&#xff0c;可…

KaliLinux安装burpsuite(超详细)

注意事项 1.注意linux位数 安装jdk之前先输出uname -a&#xff0c;看看kali linux是32位的还是64位&#xff0c;例如此处我的kali是32位的&#xff0c;因此需下载的是32位的jdk 2.jdk版本 jdk版本最好是oracle的&#xff0c;若使用的是openjdk很可能会出现burpsuite闪退现象…

远程访问本地jupyter notebook服务 - 无公网IP端口映射

文章目录 前言视频教程1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 转载自远控源码文章&#xff1a;公网远程访问jupyter notebook【cpolar内网穿透】 前言 Jupyter Notebook&am…

【Linux】信号的保存信号的捕捉信号集零碎知识点总结

【Linux】信号的保存&信号的捕捉&信号集&零碎知识点总结 一、信号的保存1.1 信号几种概念1.2 信号在内核中的表示 二、信号的捕捉了解用户态和内核态2.1 捕捉过程2.2 信号的捕捉方法2.3 信号捕捉规则2.4 多信号屏蔽问题 三、信号集3.1 概念3.2 信号集&#xff08;s…

【视频教程解读】Window上安装和使用autogluon V0.7

1.使用conda安装的python环境 教程使用的是极简版miniconda,由于我们的电脑中安装了anaconda&#xff0c;所以不需要进行进一步安装。python版本为3.9&#xff0c;博客里面有anaconda和python版本的对应关系。注意查看版本autogluon V0.4需要3.8或者3.9和3.10&#xff0c;pip版…

2023年第二十届五一数学建模B题:快递需求分析问题-思路详解

一、题目简析 今年的B题是一道较为综合的题目&#xff0c;包括了数据分析、综合评价、时间序列预测、最优化问题以及概率估计问题。考察范围广&#xff0c;但是整体看来题目背景简单&#xff0c;切入点多&#xff0c;难度适中。 二、逐问思路 1.问题1&#xff1a;附件1为该快…

私有GitLab仓库 - 本地搭建GitLab私有代码仓库并随时远程访问「内网穿透」

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar内网穿透5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 转载自远控源码文章&#xff1a;Linux搭建GitLab私有仓库&#xff0c;并内网穿透实现公…

迷你主机安装openwrt软路由系统(附启动盘制作教程+ISO、IMG镜像文件)

之前在迷你主机上刷了一个openwrt的软路由&#xff0c;安装过程分享给大家&#xff0c;镜像文件在文章末尾~ 一般需要做软路由系统的机器&#xff0c;是需要至少两个网口的&#xff0c;一个做wan口&#xff0c;一个做lan口 由于其他因素&#xff0c;不能直接将openwrt直接安装…