说明:该文章是学习 黑马程序员在B站上分享的视频 黑马程序员python教程,8天python从入门到精通而记录的笔记,笔记来源于本人。 若有侵权,请联系本人删除。笔记难免可能出现错误或笔误,若读者发现笔记有错误,欢迎在评论里批评指正。此笔记对应的doc文件的百度网盘下载链接为 Python入门(黑马)的学习笔记,提取码:1b3k。另外,本次笔记加了 gif动图,使用免费的potplayer播放器可以控制gif的播放进度。

一、初识对象
1.学习目标
理解并使用对象完成数据组织的思路。
2.什么是数据的组织
注:图片中的“姓别”应为“性别”,估计是笔误。
程序中的反面教材:
3.使用对象组织数据(设计类、创建对象、对象属性赋值)
4.本节的演示
如下图所示,打开软件,创建两个文件夹“第一阶段”与“第二阶段”,然后利用Ctr按住不放选中多个文件、剪切快捷键Ctr+X、粘贴快捷键Ctr+V将相应的文件移动到对应的文件夹。
“第一阶段”应当是一个文件夹,应如下图所示,删去对应的“init.py”文件。
如下图,在文件夹中“第二阶段”创建一个名为“01_面向对象”的文件夹,并创建一个名为“01_初始对象”的py文件。
编写代码右键并运行。代码如下,可参考注释进行理解。
# 1.设计一个类(类比生活中:设计一张登记表)
class Student:
name = None # 记录学生姓名
gender = None # 记录学生性别
nationality = None # 记录学生国籍
native_place = None # 记录学生籍贯
age = None # 记录学生年龄
# 2.创建一个对象(类比生活中:打印一张登记表)
stu_1 = Student # stu_1既是变量又是对象
# 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)
print(stu_1.age)
5.本小节的总结
二、类的成员方法
1.学习目标
掌握类的定义和使用语法;掌握成员方法的使用;掌握self关键字的作用。
2. 类的定义和使用(类包括成员变量和成员方法、方法的定义)
方法:定义在类内部的函数。
注:self只是必须写到方法里,它将成员变量传到成员方法里面,在传参的时候可以当它不存在。
3.类的注意事项
4.本节的代码演示
先打开软件,创建一个名为“02_成员方法”的py文件。
编写代码并运行。代码如下,可参考注释进行理解。
"""
演示面向对象类中的成员方法定义和使用
"""
# 定义一个带有成员方法的类
class Student:
name = None # 学生的姓名
def say_hi(self): # 在定义方法时需要要有self,在传参时可以当它不存在
# 在方法中,访问类的成员变量需要加self
print(f"大家好呀,我是{self.name},欢迎大家多多关照")
def say_hi2(self, msg):
print(f"大家好,我是:{self.name},{msg}")
# 基于类创建对象
stu = Student()
stu.name = "周杰轮"
stu.say_hi()
stu.say_hi2("哎哟不错哟")
stu2 = Student()
stu2.name = "林俊节"
stu2.say_hi2("小伙子我看好你")
5.本小节的总结
三、类和对象
1.学习目标
掌握使用类描述现实世界事物的思想;掌握类和对象的关系;理解什么是面向对象。
2. 现实世界的事物和类的关系
如下图所示,现实世界中的事物其实总的来说可以归纳为两个特征:属性和行为。至于如何理解,请看下图展示的例子。现实世界中的事物无非就分为事和物两种。它的属性就是何时、何地、谁去做,行为就是登记、检测、查结果,打扫卫生一样也有属性和行为。对于物,比如说手机,同样具有属性和行为。可见程序中的类,可以完美的描述现实世界的事物。
3. 类和对象的关系
为了理解类与对象的关系,这里举一个例子。如图,比如在我们的现实生活中,我们想要生产事物,假设我们要生产一个闹钟,在生产之前需要有设计图纸。在图纸中,规划了闹钟的一些属性,比如厚度、尺寸等,以及它按时响铃的行为。当我们有了设计图纸之后,那才会开足生产线,把闹钟一个个的都生产出来,生产出来一堆的实体。
仔细想一想,这个行为跟我们在程序中设计类、创建对象是不是很像。假设在我们程序中,我就要描述一个闹钟,它的属性包含序列号和价格,行为就是响铃。把这个思想转化为代码就如下图所示,类Clock的成员变量id、price用来记录序列号和价格,方法ring用来响铃。
那当我们在程序中,把这个类设计好之后,就可以跟我们生活中开生产线,生产实体一样,我们也可以基手我们设计好的这个类去产生具体的对象了。所以,面向对象编程说白了就是让对象干活。
4.本节的代码演示
先打开软件,创建一个名为“03_类和对象”的py文件。
编写代码并运行。代码如下,可参考注释进行理解。
# 设计一个闹钟类
class Clock:
id = None # 序列化
price = None # 价格
def ring(self):
import winsound # 导入winsound,让电脑发出声音
winsound.Beep(2000, 3000) # 频率2000Hz,持续时间3000ms
# 构建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()
Python入门
注:试了优快云几个能上传视频(优快云视频、b站、优酷)的办法, 只有优酷支持手动播放,密码为 h78jd9873,设密码的原因是不想让一个不头不尾的视频直接被放到优酷上。另外,最好使用 电脑或者 手机网页版打开。试了下,手机的优快云点输入密码的地方,居然弹不出键盘,奇怪的bug。
5.本小节的总结
四、构造方法
1.学习目标
掌握使用构造方法向成员变量赋值。
2.构造方法的引入
3.什么是构造方法
4.构造方法的注意事项
5.本节的代码演示
先打开软件,创建一个名为“04_构造方法”的py文件。
编写代码并运行。代码如下,可参考注释进行理解。
"""
演示类的构造方法
"""
# 演示使用构造方法对成员变量进行赋值
# 构造方法的名称:__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类创建了一个类对象")
stu = Student("周杰轮", 31, "18500006666")
# 打印成功,说明在创建对象时,方法__init__就跟着自动执行
print(stu.name)
print(stu.age)
print(stu.tel)
6.本小节的总结
7. 练习案例:学生信息录入
五、其它内置方法
1.学习目标
掌握几种常用的类内置方法。
2.魔术方法
3.__str__字符串方法
4.__lt__小于符号比较方法
注:__lt__只能用于小于或大于的判断,不能用于小于等于或大于等于的判断。
5.__le__小于等于比较符号方法
注:__le__用于小于等于或大于等于的判断。
6.eq,比较运算符“==”的实现方法
7.本节的代码演示
(1) __str__字符串方法的演示
先打开软件,创建一个名为“05_其它内置方法”的py文件。
先不使用“str”编写代码并运行。代码如下,可参考注释进行理解。
"""
演示Python内置的各类魔术方法
"""
class Student:
def __init__(self, name, age):
self.name = name # 学生姓名
self.age = age # 学生年龄
stu = Student("周杰轮", 31)
print(stu)
print(str(stu))
使用“str”方法编写代码并运行。代码如下,可参考注释进行理解。发现“str”方法能控制类转换为字符串的行为,类的打印输出就不再是内存地址了,而是我们自己决定应该输出什么东西。
"""
演示Python内置的各类魔术方法
"""
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))
(2) 魔术方法“lt”的演示
如下图所示,无法直接将两个类进行比较。
继续编程,使用魔术方法“lt”确定所比较的类的成员变量后,两个类就可以进行比较了。
"""
演示Python内置的各类魔术方法
"""
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 # __lt__定义Student这个类的比较对象为成员变量age
stu1 = Student("周杰轮", 31)
stu2 = Student("林俊节", 36)
print(stu1 < stu2)
print(stu1 > stu2)
再结合下图所示,可说明“lt”只能用于大于或小于的判断,不能用于大于等于或小于等于的判断。
(3) 魔术方法“le”的演示
继续编程,通过魔术方法“le”让比较支持 <= 或 >= 的判断。运行结果如图所示,第二张图是刻意把数字改成相等的运行结果。
"""
演示Python内置的各类魔术方法
"""
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 # __lt__定义Student这个类的比较对象为成员变量age
# __le__魔术方法
def __le__(self, other):
return self.age <= other.age # 让比较支持 <= 或 >= 的判断
stu1 = Student("周杰轮", 31)
stu2 = Student("林俊节", 36)
print(stu1 <= stu2)
print(stu1 >= stu2)
(4) 魔术方法“eq”的演示
如下图所示,如果不使用魔术方法“eq”,直接对类使用比较运算符“==”,它并不会报错,这是因为它们默认比较的是内存地址。那既然是比较内存地址的话,stu1、stu2是两个独立的对象,无论怎么改,哪怕把这两个对象的数据改成一样,结果肯定都是False。
继续编程,加上魔术方法“eq”后的效果如下图。
"""
演示Python内置的各类魔术方法
"""
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 # __lt__定义Student这个类的比较对象为成员变量age
# __le__魔术方法
def __le__(self, other):
return self.age <= other.age # 让比较支持 <= 或 >= 的判断
# __eq__魔术方法
def __eq__(self, other):
return self.age == other.age
stu1 = Student("周杰轮", 36)
stu2 = Student("林俊节", 36)
print(stu1 == stu2)
8.本小节的总结
六、封装
1.学习目标
理解封装的概念;掌握私有成员的使用。
2.面向对象的三大特性(封装、继承、多态)
3.什么是封装
什么是封装?如图,我们说面向对象是将现实世界事物的属性和行为描述为我们程序世界中的类的成员变量和成员方法。那其实这一个步骤,我们就称为封装。
4.对用户隐藏的属性和行为
我们现在思考一个问题,封装既然是将现实世界中的事物去映射到程序中的类的一种思想。那么再想一下,现实世界中的事物,它是有属性和行为的,但是不代表这些属性和行为都是开放给用户去使用的,如上图,对于手机,它会有属性和行为,比如序列号、品牌、型号、长宽高这些基础属性,以及上网通话和拍照这些基础的行为,这些属性和行为对于用户来说都是开放的属性和行为。那么除了对于用户开放以外,手机中也会有一系列对于用户隐藏的属性和行为,比如说手机的运行电压、驱动信息等属性一般是无法获取的,另外,包括像程序调度、内存管理这些行为也不是对我们用户开放的。所以说,我们的手机,它会既有对用户开放的属性和行为,也会有对用户隐藏的属性和行为。
5.私有成员变量与私有成员方法
问题来了,既然我们现实世界中的事物有不公开的属性和行为,那么作为现实世界中事物在程序中映射的类是不是也应该支持对私有的不公开的属性和行为进行描述呀。那这个是支持的,我们的类中其实提供了一个叫做私有成员的形式来去支持这种行为,也就是私有的成员变量和私有的成员方法。
6.使用私有成员
私有成员无法被类对象使用,但是可以被其它的成员使用。
这是什么意思呢?如上图所示,对于手机中的,像程序调度、肉存管理这些私有的行为,又或者说运行电压、驱动信息这些私有的属性,尽管用户是不能够直接使用的,但是你想想,你手机所提供的这一系列公开的行为中是不是会需要用到这些私有的内容呀。比如说你的上网、通话、拍照在运行之前是不是都要检查一下手机的电压是否正常?那包括像我开启了其他的程序,是不是需要进行内存的管理、程序的调度呀?那就是说这些私有的东西,并不是给用户使用的,而是给它自己的功能去使用的,也就是给内部去使用。
那现实生活中是这个样子,那在我们程序中呢?其实也是这个样子,在我们程序中,私有的成员对于类对象来说,是没有办法直接使用。但是我们类中的其它成员却是可以访问这些私有的成员的。
7.本节的代码演示
先打开软件,创建一个名为“06_封装”的py文件。
如下图所示,编写一段代码来验证私有成员的变量和方法都不能被类直接使用。
"""
演示面问对象封装思想中私有成员的使用
"""
# 定义一个类,内含私有成员变量和私有成员方法
class Phone:
__current_voltage = None # 当前手机运行电压
def __keep_single_core(self):
print("让CPU以单核模式运行")
phone = Phone()
phone.__keep_single_core()
print(phone.__current_voltage)
编写代码并运行。代码如下,可参考注释进行理解。说明私有的成员属性和成员方法只可以让类的内部自己使用,而无法在外面通过类的对象进行访问。
"""
演示面问对象封装思想中私有成员的使用
"""
# 定义一个类,内含私有成员变量和私有成员方法
class Phone:
__current_voltage = 1 # 当前手机运行电压
def __keep_single_core(self):
print("让CPU以单核模式运行")
# 定义一个公开的方法,假设用来进行5G通话
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()
8.本小节的总结
9.私有成员的意义
10.练习案例:设计带有私有成员的手机
进行代码的演示(为了便于管理文件,先将本节之前的代码文件改成“06_1_封装”):
创建一个名为“06_2_封装课后练习题”的py文件。
编写代码并运行。代码如下,可参考注释进行理解。
"""
面向对象-封装特性课后练习题 的演示
设计带有私有成员的手机
"""
# 设计一个类,用来描述手机
class Phone:
# 提供私有成员变量:__is_5g_enable
__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()
七、继承
7.1 继承的基础语法
1.学习目标
理解继承的概念;掌握继承的使用方式;掌握pass关键字的作用。
2.继承的引出
3.继承的含义及单继承
4.多继承
5.多继承注意事项
6.本节的代码演示
创建一个名为“07_1_继承的基础语法”的py文件。
为了熟悉单继承的语法,如下编写代码并运行。代码可参考注释进行理解。
"""
演示面向对象:继承的基础语法
"""
# 演示单继承
class Phone:
IMEI = None # 序列号
producer = "HM" # 厂商
def call_by_4g(self):
print("4g通话")
class Phone2022(Phone):
face_id = "10001" # 面部识别ID
def call_by_5g(self):
print("2022年新功能:5g通话")
phone = Phone2022()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
为了熟悉多继承,如下编写代码后运行(注释快捷键Ctr+/)。
"""
演示面向对象:继承的基础语法
"""
# 演示单继承
class Phone:
IMEI = None # 序列号
producer = "HM" # 厂商
def call_by_4g(self):
print("4g通话")
class Phone2022(Phone):
face_id = "10001" # 面部识别ID
def call_by_5g(self):
print("2022年新功能:5g通话")
# phone = Phone2022()
# print(phone.producer)
# phone.call_by_4g()
# phone.call_by_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 # 有时不想加东西,但由于语法要求必须要有内容的地方,需使用 占位符pass
phone = MyPhone()
phone.call_by_4g()
phone.read_card()
phone.write_card()
phone.control()
为了验证多个父类中,如果有同名的成员, 先继承的保留,后继承的被覆盖,如下编写代码并运行(父类Phone和NFCReader中均有成员变量producer,而且值还不一样)。
"""
演示面向对象:继承的基础语法
"""
# 演示单继承
class Phone:
IMEI = None # 序列号
producer = "ITCAST" # 厂商
def call_by_4g(self):
print("4g通话")
class Phone2022(Phone):
face_id = "10001" # 面部识别ID
def call_by_5g(self):
print("2022年新功能:5g通话")
# phone = Phone2022()
# print(phone.producer)
# phone.call_by_4g()
# phone.call_by_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 # 有时不想加东西,但由于语法要求必须要有内容的地方,需使用 占位符pass
phone = MyPhone()
# phone.call_by_4g()
# phone.read_card()
# phone.write_card()
# phone.control()
# 演示多继承下,父类成员名一致的场景
print(phone.producer)
7.本小节的总结(含占位符pass)
7.2 复写和使用父类成员
1.学习目标
掌握复写父类成员的语法;掌握如何在子类中调用父类成员。
2.复写
3.调用父类同名成员
4.本节的代码演示
创建一个名为“07_2_复写和使用父类成员”的py文件。
为了熟悉复写的语法,编写如下代码并运行,可参考注释进行理解。
class Phone:
IMEI = None # 序列号
producer = "ITCAST" # 厂商
def call_by_5g(self):
print("使用5g网络进行通话")
# 定义子类,复写父类成员
class MyPhone(Phone):
producer = "ITHEIMA" # 复写父类的成员属性
def call_by_5g(self):
print("开启CPU单核模式,确保通话的时候省电")
print("使用5g网络进行通话")
print("关闭CPU单核模式,确保性能")
phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
为了学习调用父类同名成员的方式1,如下编程并运行代码展示效果。
class Phone:
IMEI = None # 序列号
producer = "ITCAST" # 厂商
def call_by_5g(self):
print("使用5g网络进行通话")
# 定义子类,复写父类成员
class MyPhone(Phone):
producer = "ITHEIMA" # 复写父类的成员属性
def call_by_5g(self):
print("开启CPU单核模式,确保通话的时候省电")
# 调用父类同名成员,2种方式
# 方式1
print(f"父类的厂商是:{Phone.producer}")
Phone.call_by_5g(self)
print("关闭CPU单核模式,确保性能")
phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
为了学习调用父类同名成员的方式2,如下编程并运行代码展示效果。
class Phone:
IMEI = None # 序列号
producer = "ITCAST" # 厂商
def call_by_5g(self):
print("使用5g网络进行通话")
# 定义子类,复写父类成员
class MyPhone(Phone):
producer = "ITHEIMA" # 复写父类的成员属性
def call_by_5g(self):
print("开启CPU单核模式,确保通话的时候省电")
# 调用父类同名成员,2种方式
# # 方式1
# print(f"父类的厂商是:{Phone.producer}")
# Phone.call_by_5g(self)
# 方式2
print(f"父类的厂商是:{super().producer}")
super().call_by_5g()
print("关闭CPU单核模式,确保性能")
phone = MyPhone()
phone.call_by_5g()
print(phone.producer)
5.本小节的总结
八、类型注解
8.1变量的类型注解
1.学习目标
理解为什么使用类型注解;掌握变量的类型注解语法。
2.为什么需要类型注解
3.什么是类型注解(针对变量或函数)
4.类型注解的语法(两种方式)
5.类型注解的限制
6.快捷键“Alt+Enter”快速导包
在编写程序时,快捷键“Alt+Enter”可方便我们快速导包,使用方式如图。这里以导入random为例进行介绍,输入ramdom后,使用快捷键“Alt+Enter”,然后根据提示即可快速导包。
7.本节的代码演示
创建一个名为“08_1_变量的类型注解”的py文件。
然后在代码中练习本次学到的类型注解的语法,运行一下,没有报错。
"""
演示变量的类型注解
"""
import json
import random
# 基础数据类型注解
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: list[int] = [1, 2, 3]
my_tuple: tuple[int, str, bool] = (1, "itheima", True)
my_dict: dict[str, int] = {"itheima": 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
8.本小节的总结
8.2函数(方法)的类型注解
1.学习目标
掌握为函数(方法)形参进行类型注解;掌握为函数(方法)返回值进行类型注解。
2.函数(方法)的类型注解(形参、返回值)
注:函数(方法)的类型注解是提示性的,并不是强制性的。
3.本节的代码演示
创建一个名为“08_2_函数(方法)的类型注解”的py文件。
然后在代码中练习本次学到的关于函数(方法)类型注解的语法,运行一下,没有报错。
"""
演示对函数(方法)进行类型注解
"""
def add(x: int, y: int):
return x + y
# 对返回值进行类型注解
def func(data: list) -> list:
return data
print(func(1)) # 此句代码说明在函数中进行类型注解,它也同样只是提示性的,而非决定性的
4.本小节的总结
8.3 Union类型
1.学习目标
理解Union类型;掌握使用Union进行联合类型注解。
2. Union类型
3.本节的代码演示
创建一个名为“08_3_联合类型的类型注解Union”的py文件。
然后在代码中练习本次学到的关于联合类型的类型注解Union的语法,运行一下,没有报错(快捷键Ctr+P弹出提示,提示中间的符号“|”表示或的意思)。
"""
演示Union联合类型注解
"""
# 使Union类型,必须先导包
from typing import Union
my_list: list[Union[int, str]] = [1, 2, "itheima", "itcast"]
def func(data: Union[int, str]) -> Union[int, str]:
pass
func(2)
4.本小节的总结
九、多态
1.学习目标
理解多态的概念;理解抽象类(接口)的编程思想。
2.什么是多态
3.抽象类(接口)
4.本节的代码演示
先打开软件,创建一个名为“09_多态”的py文件。
编写代码并运行。代码如下,可参考注释进行理解。
"""
演示面向对象的多态特性以及抽象类(接口)的使用
"""
# ------------------1.演示多态的语法--------------
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("汪汪汪")
class Cat(Animal):
def speak(self):
print("喵喵喵")
def make_noise(animal: Animal):
"""制造点噪音,需要传入Animal对象"""
animal.speak()
# 演示多态,使用2个子类对象来调用函数
dog = Dog()
cat = Cat()
make_noise(dog)
make_noise(cat)
# ------------------2.演示抽象类--------------
class AC:
def cool_wind(self):
"""制冷"""
pass
def hot_wind(self):
"""制热"""
pass
def swing_l_r(self):
"""左右摆风"""
pass
class Midea_AC(AC):
def cool_wind(self):
print("美的空调制冷")
def hot_wind(self):
print("美的空调制热")
def swing_l_r(self):
print("美的空调左右摆风")
class GREE_AC(AC):
def cool_wind(self):
print("格力空调脚冷")
def hot_wind(self):
print("格力空调制热")
def swing_l_r(self):
print("格力空调左右摆风")
def make_cool(ac: AC):
ac.cool_wind()
midea_ac = Midea_AC()
gree_ac = GREE_AC()
make_cool(midea_ac)
make_cool(gree_ac)
5.本小节的总结
十、综合案例(数据分析)
1.学习目标
使用面向对象思想完成数据读取和处理;基于面向对象思想重新认知第三方库使用(PyEcharts)。
2.案例需求
3.本节的代码演示
先打开软件,创建一个名为“数据分析案例”的文件夹,创建一个名为“main”的py文件。
先在文件“mian.py”中写好本案例的主要逻辑顺序,然后创建一个名为“data_define”的py文件用来定义处理数据的类,根据数据内容暂时输入以下代码。
"""
数据定义的类
"""
# 记录数据
class Record:
def __init__(self, data, order_id, money, province):
# 根据文件,说明需要定义4个成员变量
self.date: str = data # 订单日期
self.order_id: str = order_id # 订单ID
self.money: int = money # 订单金额
self.province: str = province # 销售省份
def __str__(self):
return f"{self.date},{self.order_id},{self.money},{self.province}"
然后创建一个名为“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) -> list[Record]:
f = open(self.path, "r", encoding="UTF-8")
record_list: list[Record] = []
for line in f.readlines():
# print(line) # 测试使用
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
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)
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:/test/2-1/2011年1月销售数据.txt")
json_file_reader = JsonFileReader("D:/test/2-1/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)
之后回到文件“main.py”中,进行数据的计算和可视化开发的编程,运行结果如下。
"""
面向对象,数据分析案例,主业务逻辑代码
实现步骤:
1.设计一个类,可以完成数据的时装
2.设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功能
3.读取文件,生产数据对象
4.进行数据需求的逻辑计算(计算每一天的销售额)
5.通过PyEcharts进行图形绘制
"""
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,LabelOpts,InitOpts
# --------------------------数据处理-----------------------------
text_file_reader = TextFileReader("D:/test/2-1/2011年1月销售数据.txt")
json_file_reader = JsonFileReader("D:/test/2-1/2011年2月销售数据JSON.txt")
jan_data: list[Record] = text_file_reader.read_data() # 1月份的数据
feb_data: list[Record] = json_file_reader.read_data() # 2月份的数据
# 将2个月份的数据合并1个list来存储
all_data: list[Record] = jan_data + feb_data
# 开始进行数据计算 —— 计算各个日期的销售额
# 将数据做成字典:{“2011-01-01":1534,"2011-01-02":300,"2011-01-03":650}
data_dict = {}
for record in all_data:
if record.date in data_dict:
# 当前日期已经有记录了,所以和老记录做累加即可
data_dict[record.date] += record.money
else:
# 当前日期已经无记录,将第一个销售金额记入即可
data_dict[record.date] = record.money
# print(data_dict) # 测试
# --------------------------可视化开发-----------------------------
bar = Bar(
init_opts=InitOpts(theme=ThemeType.LIGHT)
)
bar.add_xaxis(list(data_dict.keys())) # 添加X轴的数据
bar.add_yaxis("销售额", list(data_dict.values()),
label_opts=LabelOpts(is_show=False)
) # 添加y轴的数据
bar.set_global_opts(
title_opts=TitleOpts(title="每日销售额"),
)
bar.render("每日销售额柱状图.htmL")
好了,本章的笔记到此结束,谢谢大家阅读。