某公司有两份数据文件:“2011年1月销售数据.txt”和“2011年2月销售数据JSON.txt”。前者是普通文本文件,使用逗号分隔数据记录,内容依次为日期、订单编号、销售额和销售省份;后者则是JSON格式的数据,内容依次为日期、订单编号、销售额和销售省份。现在需要对这两份数据进行分析和处理,要求是使用面向对象的编程思想来读取和处理数据,计算每日的销售额,并利用Pyecharts库以柱状图的形式展示结果。
文件部分数据如下:
【需求分析】
①数据定义类
代码语言:python代码运行次数:0复制"""
数据定义类
Record类用于封装销售数据中每一条记录
"""
class Record:
# 该构造方法接受日期、订单编号、销售额和省份,并将它们存储为类的实例变量
def __init__(self,date,order_id,money,province):
self.date = date # 订单日期
self.order_id = order_id # 订单编号
self.money = money # 订单金额
self.province = province # 销售省份
# 字符串表示法,方便打印Record对象的内容,返回一个格式化的字符串
def __str__(self):
return f"{self.date},{self.order_id},{self.money},{self.province}"
【分析】
Record 类的主要作用是将销售数据的每一条记录封装为一个对象,提供了一个清晰的结构来存储和访问这些数据。通过该类,可以方便地创建多个销售记录对象,并在需要时以易读的格式输出它们。在整个分析和可视化过程中,Record 类将被用于读取和存储来自两个数据文件的销售记录,之后便可通过遍历这些对象来计算每日的销售额,并利用 Pyecharts 库生成柱状图展示结果。
②文件读取类
代码语言:python代码运行次数:0复制"""
文件相关的类定义
"""
# 导入 json 模块,用于处理JSON文件
import json
# 导入 Record 类,以便在其他类中创建记录对象
from data_define import Record
# 定义一个抽象类,用于顶层设计,定义了文件读取的接口
class FileReader:
# 抽象方法,强制子类实现相应的读取方法,并返回一个包含Record对象的列表
def read_data(self)->list[Record]:
pass
# 子类TextFileReader继承父类FileReader,用于从文本文件中读取数据
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来存储Record对象
record_list:list[Record]=[]
# 循环读取每一行数据
for line in f.readlines():
line=line.strip() # 消除读取到的每一行数据中的 n
data_list=line.split(",")
# print(data_list)
# 输出内容:['2011-01-01', '4b34218c-9f37-4e66-b33e-327ecd5fb897', '1689', '湖南省']……
record=Record(data_list[0],data_list[1],int(data_list[2]),data_list[3])
# print(record)
# 输出内容:2011-01-01,4b34218c-9f37-4e66-b33e-327ecd5fb897,1689,湖南省
record_list.append(record)
f.close()
return record_list
# 子类JsonFileReader继承自父类FileReader,用于从JSON文件中读取数据
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():
# 将json数据转换为Python字典
data_dict=json.loads(line)
# 从字典中提取相应的字段
record=Record(data_dict["date"],data_dict["order_id"],data_dict["money"],data_dict["province"])
print(record)
record_list.append(record)
f.close()
return record_list
【分析】
这段代码实现了一个简单的文本文件读取器,用于读取不同格式的文件(文本和 JSON),并将文件中的每一行数据转换为 Python 对象,便于在后续程序中管理和操作这些数据。
在本案例中,将文本文件中的每一行数据转换为 Python 对象的操作也可称为 “数据反序列化。
- 数据序列化: 将数据结构或对象状态转换为可存储或传输的格式的过程。这一过程使得数据能够被有效地保存到文件中或通过网络进行传输。在序列化过程中,数据被转换为一种特定格式,例如文本格式(如 JSON、XML)、二进制格式等,以便于存储和恢复。
- 数据反序列化: 将已序列化的数据转换回其原始数据结构或对象状态的过程。反序列化是序列化的逆过程,使得应用程序能够再次使用以前存储或传输的数据信息。
实现数据反序列化的基本步骤:
- 定义对象类
- 读取数据源:使用 Python 的内置 open() 函数打开文件并读取内容
- 解析数据:文本文件通常需要按行读取,使用字符串操作进行拆分;JSON文件需使用json模块解析为Python字典
- 创建对象
- 处理错误
思考:那为什么要将文件中的每一行数据转换为 Python 对象呢?
回答:
- 封装性: 对象可以将相关数据和方法封装在一起,使得数据结构更加清晰。例如,Record 对象可以包含日期、订单号、金额和省份等属性,所有相关信息集中到一起,便于管理。
- 易于操作: 对象可以包含操作其数据的方法,方便对数据进行处理(如排序、筛选、计算等),灵活性高。
- 可扩展性: 通过面向对象的设计,可以更容易地实现继承和多态,创建复杂数据结构和业务逻辑。如果未来需要追加新的属性或行为(例如添加方法计算订单的税费),可直接在 Record 类中进行扩展,而不必去修改数据读取的逻辑。
- 提高可读性和可维护性: 使用对象后,开发者可以通过方法名和属性名一目了然地理解程序的意图。除此之外,对象可以独立于其使用环境进行测试,简化了调试和维护流程。
- 模拟现实世界: 通过对象,可以更准确地模拟现实世界中的事物。例如,订单不仅仅包含数据,还可以有与之相关的行为和状态,使代码更贴近实际应用。
③数据计算以及图表绘制
代码语言:python代码运行次数:0复制# 导入必要的库和之前定义的类
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
# 创建TextFileReader和JsonFileReader的实例,读取数据到列表中
text_file_reader=TextFileReader("D:/2011年1月销售数据.txt")
jan_data:list[Record]=text_file_reader.read_data()
json_file_reader=JsonFileReader("D:/2011年2月销售数据JSON.txt")
feb_data:list[Record]=json_file_reader.read_data()
# 将两个月份的数据合并为一个list来存储
all_data:list[Record]=jan_data feb_data
# 计算每日销售额
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)
# 可视化图表开发
bar=Bar(init_opts=InitOpts(theme=ThemeType.LIGHT))
# 添加x轴数据,显示日期
bar.add_xaxis(list(data_dict.keys()))
# 添加y轴数据,显示销售额
bar.add_yaxis("销售额",list(data_dict.values()),label_opts=LabelOpts(is_show=False))
bar.set_global_opts(
title_opts=TitleOpts(title="每日销售额")
)
bar.render()
【分析】
这段代码读取了两个不同格式的销售数据文件(一个文本文件和一个JSON文件),合并了数据,计算了每日的销售额,并使用Pyecharts库进行了可视化。
运行后打开render.html
文件并在浏览器中查看创建的柱状图。
程序实现流程:
- 定义数据类 Record 封装每条销售记录
- 设计抽象类 FileReader 定义文件读取接口,并实现两个子类 TextFileReader 和 JsonFileReader ,分别处理文本文件和 JSON 文件的读取逻辑。
- 进行数据需求的逻辑计算(计算每日销售额)
- 利用 Pyecharts 绘制柱状图展示销售数据
通过这种结构化的面向对象设计,代码结构分明,可维护性和可扩展性高。