Python(13) -- 面向对象
1. 初识对象
在Python中,对象是一个核心概念,它是面向对象编程的基础。对象是通过类定义的数据结构的实例,包含数据成员(类变量和实例变量)和方法。
1.在程序中设计表格,我们称之为:设计类(class)
2. 在程序中打印生产表格,我们称之为:创建对象
3. 在程序中填写表格,我们称之为:对象属性赋值
2. 成员方法
2.1 类:
- 类的属性,称之为:成员变量
- 类的行为,称之为:成员方法
2.2 语法:
2.3 self:
- 表示类对象本身的意思
- 只有通过self,成员方法才能访问类的成员变量
- self出现在形参列表中,但是不占用参数位置,无需理会
3. 类和对象
1.现实世界的事物由什么组成?
属性 行为
类也可以包含属性和行为,所以使用类描述现实世界事物是非常合适的
2. 类和对象的关系是什么?
类是程序中的“设计图纸”
对象是基于图纸生产的具体实体(类是实体对象)
3. 什么是面向对象编程?
面向对象编程就是,使用对象进行编程。
即,设计类,基于类创建对象,并使用对象来完成具体的工作
4. 构造方法
1. 构造方法:
__init__,注意init前后的2个下划线符号
2. 构造方法的作用:
- 构建类对象的时候会自动运行
- 构建类对象的传参会传递给构造方法,借此特性可以给成员变量赋值
3. 注意事项:
- 构造方法不要忘记self关键字
- 在方法内使用成员变量需要使用self
5. 内置方法
方法 | 功能 |
__init__ | 构造方法,可用于创建类对象的时候设置初始化行为 |
__str__ | 用于实现类对象转字符串的行为 |
__lt__ | 用于2个类对象进行小于或大于比较 |
__le__ | 用于2个类对象进行小于等于或大于等于比较 |
__eq__ | 用于2个类对象进行相等比较 |
--str--:字符串方法
--lt--:小于符号比较方法
--le--:小于等于比较符号方法
--eq--:比较运算符实现方法
6. 封装
面向对象包含3大主要特性:
封装 继承 多态
封装:
将现实世界事物的属性和行为,在类中描述为成员变量和成员方法,即为封装。
私有成员:
现实事物有部分属性和行为是不公开对使用者开放的。
同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了
私有成员变量和成员方法的命名均以__作为开头即可
注意:
类对象无法访问私有成员
私有变量无法赋值,也无法获取值
类中的其它成员可以访问私有成员
7. 继承
7.1 继承的基础语法
继承:将从父类那里继承(复制)来成员变量和成员方法(不含私有)
单继承:
一个类继承另一个类
多继承:
一个类继承多个类,按照顺序从左向右依次继承
多继承中,如果父类有同名方法或属性,先继承的优先级高于后继承
pass关键字:用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
7.2 复写与使用父类成员
子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。
即:在子类中重新定义同名的属性或方法即可。
一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员 如果需要使用被复写的父类的成员,需要特殊的调用方式:
方式1: 调用父类成员
- 使用成员变量:父类名.成员变量
- 使用成员方法:父类名.成员方法(self)
方式2: 使用super()调用父类成员
- 使用成员变量:super().成员变量
- 使用成员方法:super().成员方法()
注意:只能在子类内调用父类的同名成员。 子类的类对象直接调用会调用子类复写的成员
8. 类型注解
8.1 变量的类型注解
在代码中涉及数据交互之时,对数据类型进行显式的说明,可以帮助:
- PyCharm等开发工具对代码做类型推断协助做代码提示
- 开发者自身做类型的备注
类型注解:
- 变量的类型注解
- 函数(方法)的形参和返回值的类型注解
变量的类型注解语法
- 语法1: 变量: 类型
- 语法2: 在注释中,# type: 类型
注意:类型注解只是提示性的,并非决定性的。数据类型和注解类型无法对应也不会导致错误
8.2 函数(方法)的类型注解
形参注解:
注意,返回值类型注解的符号使用: ->
返回值注解:
8.3 Union类型
可以定义联合类型注解
- 导包:from typing import Union
- 使用:Union[类型, ......, 类型]
9. 多态
多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
多态常作用在继承关系上.
比如
- 函数(方法)形参声明接收父类对象
- 实际传入父类的子类对象进行工作
即: 以父类做定义声明 以子类做实际工作 用以获得同一行为, 不同状态
抽象类(接口):
包含抽象方法的类,称之为抽象类。抽象方法是指:没有具体实现的方法(pass)称之为抽象方法
作用:
- 多用于做顶层设计(设计标准),以便子类做具体实现。
- 也是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法 并配合多态使用,获得不同的工作状态。
10. 综合案例
某公司,有2份数据文件,现需要对其进行分析处理,计算每日的销售额并以柱状图表的形式进行展示。
- 1月份数据是普通文本,使用逗号分割数据记录,从前到后分别是(日期,订单id,销售额,销售省份)
- 2月份数据是JSON数据,同样包含(日期,订单id,销售额,销售省份)
data:
"""
数据定义的类
"""class Record:def __init__(self, date, order_id, money, province):self.date = date # 订单日期self.order_id = order_id # 订单idself.money = money # 订单金额self.province = province # 销售省份def __str__(self):return f"{self.date}, {self.order_id}, {self.money}, {self.province}"
file:
"""
和文件相关的类定义
"""
import jsonfrom data_define import Record# 先定义一个抽象类用来做顶层设计,确定有哪些功能需要实现
class FileReader:def read_data(self) -> list[Record]:"""读取文件的数据,读到的每一条数据都转换为Record对象,将他们都封装在List内返回即可"""passclass 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():line = line.strip() # 显出读取到的每一行的\ndata_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_listclass 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_listif __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)
main:
"""
面向对象
实现步骤:
设计一个类,完成读取文件和数据封装
设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功能
读取文件,生产数据对象
进行数据需求的逻辑计算(计算每一天的销售额)
通过PyEcharts进行图形绘制
"""from file_define import FileReader, TextFileReader, JsonFileReader
from data_define import Record
from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType
from collections import defaultdict# 数据读取
text_file_reader = TextFileReader("./2011年1月销售数据.txt")
json_file_reader = JsonFileReader("./2011年2月销售数据JSON.txt")
all_data = text_file_reader.read_data() + json_file_reader.read_data()# 数据处理(使用defaultdict更安全)
data_dict = defaultdict(int)
for record in all_data:data_dict[record.date] += record.money# 按日期排序
sorted_dates = sorted(data_dict.keys())
sorted_values = [data_dict[date] for date in sorted_dates]# 可视化图表开发(修正后的写法)
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT,width="1200px",height="600px"
))bar.add_xaxis(sorted_dates)
bar.add_yaxis("销售额", sorted_values,label_opts=opts.LabelOpts(is_show=False),markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max", name="最大值"),opts.MarkPointItem(type_="min", name="最小值")]))bar.set_global_opts(title_opts=opts.TitleOpts(title="每日销售额趋势", pos_left="center"),toolbox_opts=opts.ToolboxOpts(is_show=True),xaxis_opts=opts.AxisOpts(name="日期",axislabel_opts={"rotate": 45} # 倾斜45度防止重叠),yaxis_opts=opts.AxisOpts(name="销售额(元)"),datazoom_opts=[opts.DataZoomOpts()] # 添加缩放功能
)# 渲染图表
bar.render("daily_sales.html")
print("图表已生成:daily_sales.html")