Python 数据可视化 matplotlib matplotlib 是一个用于创建静态、动态和交互式可视化图形的 Python 库 。它被广泛用于数据可视化,并且可以与多种操作系统和图形后端一起工作。
matplotlib 的主要组成部分是 pyplot ,它是一个类似于 MATLAB 的绘图框架。pyplot 提供了一个 MATLAB 式的接口,可以隐式地创建图形和轴,使得绘图变得简单。
在Pycharm 中需要安装 matplotlib 包 pip install matplotlib
mpld3 mpld3 是一个 Python 库,优势在于它能够将静态的 Matplotlib 图形转换为具有交互性的 D3.js 图形 ,使得用户可以通过鼠标交互 来探索和操作图形。
pip install mpld3
Spyder Pycharm 中绘图可能会出现图片无法正确显示颜色等问题,建议可视化代码运行在 Spyder 中。
安装网址: Spyder:https://www.spyder-ide.org
注:以下可视化代码截图,将会从 Spyder 中运行后截取。
制图步骤 ① 安装 matplotlib pip install matplotlib
② 导入 matplotlib.pyplot import matplotlib.pyplot as plt
或 from matplotlib import pyplot as plt
③ 准备数据 准备所需的可视化数据。
④ 绘制图形 使用plt
中的函数来绘制您想要的图形。以下是一些常见图形的绘制方法:
线图 :
散点图 :
条形图 :
直方图 :
饼图 :
1 plt.pie(sizes, labels=labels)
⑤ 定制图形 可以添加标题、轴标签、图例以及调整轴的范围等
1 2 3 4 5 6 7 8 plt.title("My Plot" ) plt.xlabel("X Axis" ) plt.ylabel("Y Axis" ) plt.legend() plt.xlim(0 , 10 ) plt.ylim(0 , 100 ) plt.xticks(range (0 , 10 )) plt.yticks(range (0 , 10 ))
⑥ 显示或保存图形 最后,使用 plt.show()
来显示图形,或者使用 plt.savefig()
来保存图形到文件
1 2 3 plt.show() plt.savefig('my_plot.png' )
⑦ (可选)使用 subplots 创建多个子图 如果想在同一个窗口中显示多个图形,可以使用 plt.subplots()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fig, axs = plt.subplots(2 , 2 ) fig.suptitle('Plot of Sine Function' ) axs[0 , 0 ].plot(x1, y1) axs[0 , 1 ].scatter(x2, y2) ''' fig:表示整个图形窗口的对象(Figure)。 它是你所有子图和其他绘图元素的容器。可以通过fig来设置整个图形的属性,例如标题、大小等。 axs:表示一个包含多个子图的数组(Axes)。 通过索引访问每个子图,例如axs[0, 0]表示第一行第一列的子图,axs[1, 1表示第二行第二列的子图。 '''
⑧ (可选)Pandas Pandas 是基于 numpy 的一种工具,该工具是为解决数据分析 任务而创建的,提供了大量能使我们快速便捷地处理数据的函数和方法 ,帮我们高效地操作大型数据集,可以通过 pandas 包读取文件中数据进行绘图。
安装 pip install pandas
绘图示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import matplotlib.pyplot as plt import numpy as np x = np.linspace(0 , 10 , 100 ) y = np.sin(x) plt.plot(x, y, "-" , label="sinx" ) plt.title("Simple Plot of Sine Function" ) plt.xlabel("X-axis" ) plt.ylabel("Y-axis" ) plt.legend(loc="upper right" ) plt.show()
注意事项: matplotlib 具有高度的可定制性,在绘制复杂图形或者绘制图形不满意时,可以通过 Chatgpt 等其他语言大模型的帮助,获得更精细的控制和更理想的图形。
每个函数里面都有许多参数,如 loc,lizestyle,labeldistance 等,都学习的成本太高了也记不住,在后续常用图形中会捎带讲解,只需了解和会读。
常用图形 线图(Line Plot) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import matplotlib.pyplot as pltx = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] y = [1 , 3 , 5 , 0 , 2 , 3 , 5 , 8 ] plt.plot(x, y, color="red" , alpha=0.5 , linestyle="--" , linewidth=2 , marker="o" ) plt.title("Line Plot" ) plt.xlabel("X Axis" ) plt.ylabel("Y Axis" ) plt.grid(color="green" , alpha=0.5 , linestyle=":" , linewidth=1 , axis="x" ) plt.show()
散点图 (Scatter Plot) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from matplotlib import pyplot as pltimport numpy as npx = np.random.rand(50 ) y = np.random.rand(50 ) plt.scatter(x, y, marker="s" ) plt.title("Scatter Plot" ) plt.xlabel("X Axis" ) plt.ylabel("Y Axis" ) plt.grid(True ) plt.show()
设置值
说明
设置值
说明
.
点
s
实心正方形
,
像素
p
实心五角形
+
加号
P
实心加号
x
叉号
X
实心叉号
d
菱形
D
粗菱形
o
实心圆
h
竖正六边形
*
星形
H
横实心正六边形
|
竖线
_
短横
v
下三角
1
上花三角
^
上三角
2
下花三角
<
左三角
3
左花三角
>
左三角
4
右花三角
条形图 (Bar Chart) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from matplotlib import pyplot as pltimport randomcategories = [1 , 2 , 3 , 4 , 5 ] values = [random.randint(10 , 60 ) for i in range (5 )] plt.rcParams["font.sans-serif" ] = ["SimHei" ] plt.rcParams["axes.unicode_minus" ] = False for a, b in zip (categories, values): plt.text(a, b + 1 , b, ha="center" ) """ plt.text(x, y, s, fontsize, verticalalignment, horizontalalignment, color, **kwargs) x:标签横向坐标 y:标签纵向坐标 s:标签的内容,字符串格式, fontsize:标签字体大小 verticalalignment(va):垂直对齐方式,可以选center、top、bottom、baseline等 horizontalalignment(ha):水平对齐方式,可以选center、right、left等 color:注释文本内容的字体颜色 """ plt.bar(categories, values, width=0.5 ) plt.title("Bar Chart" ) plt.xlabel("Categories" ) plt.ylabel("Values" ) plt.legend(("测试图例" ,)) plt.show()
直方图 (Histogram) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import numpy as npfrom matplotlib import pyplot as pltdata = np.random.randn(100 ) print (data)data = np.sort(data) print (data)plt.hist(data, bins=20 , edgecolor="black" , color="skyblue" , alpha=0.7 ) plt.title("Histogram of Normal Distribution" ) plt.xlabel("Value Range" ) plt.ylabel("Frequency" ) plt.grid(axis="y" , linestyle="--" ) plt.show()
饼图 (Pie Chart) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from matplotlib import pyplot as pltlabels = ["A" , "B" , "C" , "D" ] sizes = [15 , 30 , 45 , 10 ] plt.pie(sizes, labels=labels, labeldistance=1.08 , autopct="%1.1f%%" , startangle=90 ) plt.axis("equal" ) plt.title("Pie Chart" ) plt.legend(labels, loc="upper right" ) plt.show()
注:还有一些图形有特定的使用场景,需要的时候再进行具体学习。
直方图 2d(Hist2d Plot)
面积图(Area Plot)
热力图(Heatmap)
三维图形(3D Plot)
堆叠图(Stacked Plot)
等
Python 面向对象 面向过程: 把完成某一个需求的所有步骤从头到尾逐步实现 ,根据开发需求,将某些功能独立的代码封装成一个又一个函数,最后完成的代码,就是顺序地调用不同的函数 。
面向对象: 在完成某一个需求前,首先确定要做的事情,根据事情确定不同的对象 ,在对象内部封装不同的方法,最后完成的代码,就是顺序地让不同的对象调用不同的方法 。
注:在类内叫方法 ,类外叫函数 ,其实是差不多的东西,就相差一个self (稍后介绍)。
总结: 面向过程更像是一步一步地做事,面向对象则像是把事物看作盒子,每个盒子里有自己所需的数据和功能。
面向对象的三大特征:封装、继承和多态
类和对象 定义 类 类 是对一群具有相同特征或者行为 的事务的一个统称 ,是抽象的,不能直接使用 。
在类中 特征 被称为 成员变量(属性)
在类中 行为 被称为 成员方法
类 就相当于制造飞机时的图纸 ,是一个模板 ,是负责创建对象的 。
类名 的命名规则需要满足大驼峰命名法 ,例 MyClass
每一个单词的首字母大写
单词与单词之间没有下划线
对象 对象 是由类创建出来的一个具体存在 ,可以直接使用
由哪一个类 创建出来的对象 ,就拥有在哪一个类 中定义的:属性和方法
用类实例化一个对象 就相当于根据某张图纸制造一架飞机 。
一张图纸可以造出许多架飞机,同理,一个类也能实例化出多个对象 。
语法
1 2 3 4 5 6 7 8 9 10 11 class Student : name = None age = None def say_hi (self, msg ): print (f"旅行者你好!我的名字叫{self.name} ,今年{self.age} 岁,是蒙德城连续三年的「飞行冠军」!\n{msg} " ) stu_1 = Student() stu_1.name = "安柏" stu_1.age = 16 stu_1.say_hi("欢迎来到蒙德城!" )
在 类的外部 ,通过 变量名.
访问对象的 属性和方法
在 类封装的方法中 ,通过 self.
访问对象的 属性和方法
魔术方法 在 Python 中,魔术方法(magic methods),是指以双下划线开头和结尾的特殊方法。
总览
方法
功能
__init__
构造方法,可用于创建类对象的时候设置初始化行为
__str__
用于实现类对象转字符串的行为
__lt__
用于 2 个类对象进行小于或大于比较
__le__
用于 2 个类对象进行小于等于或大于等于比较
__eq__
用于 2 个类对象进行相等比较
__init__ (构造方法) 作用:为对象的属性设置初始值 ,该方法在创建对象时会被自动调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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("迪卢克" , 25 , "12367896789" ) print (stu.name, stu.age, stu.tel)
构造方法和手动赋值的区别:
对象在创建时就保证了必要的属性被赋值,避免对象处于不完整或错误的状态。
代码简洁,不需要额外的赋值步骤。
可以封装复杂的初始化逻辑,避免手动赋值时遗漏或导致错误。
增强了属性的一致性和对象的不可变性,防止成员变量被随意修改。
有了构造方法后,每次实例化 Student
类时,你必须传递 name
、age
和 tel
这三个参数,如果你想在实例化时可以不传递参数,有几种常见的做法:
1. 为参数设置默认值 :
1 2 3 4 5 6 7 8 9 10 11 class Student : def __init__ (self, name="旅行者" , age=17 , tel="12356785678" ): self.name = name self.age = age self.tel = tel print ("Student类创建了一个类对象" ) stu = Student() print (stu.name, stu.age, stu.tel)
缺省函数 规则: 一旦某个键设了默认值,那么从这个键往后的键都必须设置默认参数。
2. 使用可变参数 :
1 2 3 4 5 6 7 8 9 10 11 class Student : def __init__ (self, **kwargs ): self.name = kwargs.get("name" , None ) self.age = kwargs.get("age" , None ) self.tel = kwargs.get("tel" , None ) print ("Student类创建了一个类对象" ) stu = Student(name="凯亚" ) print (stu.name, stu.age, stu.tel)
kwargs
:是一个可变长度的关键字参数字典,包含传递给函数的所有关键字参数。在函数调用时,所有以 key=value
形式传递的参数会存储在这个字典中。
get("name", None)
:get()
是 Python 字典类型的一个方法。它的作用是:
从字典中获取指定键 "name"
的值。
如果键 "name"
存在,就返回对应的值。
如果键 "name"
不存在,则返回你指定的默认值,这里是 None
。
__str__ 默认情况下,直接打印实例化对象 会输出这个变量所引用的对象是由哪一个类创建的对象,以及在内存中的地址 ,用 __str__
这个内置方法能够打印 自定义的内容 。
__del__ 在创建对象 时,会给对象分配一片空间存储 ,接着会自动调用 __init__
方法进行构造,那如果想删除一个对象 ,我们可以使用del
关键字 ,语法:del 对象名
注意:此时我们删除掉的是从命名空间中对删除对象的引用,而不是直接删除对象本身,如果还有其他引用指向该对象,则对象不会被删除,直到所有引用都被删除,对象才会真正被删除。
如果我们在类中创建了__del__
方法,那么销毁的时候会自动调用__del__
方法,所以如果希望在对象被销毁前,再做一些事情,比如关闭文件、释放网络连接等 ,可以使用 __del__
方法。
生命周期
一个对象从调用 类名()
创建,生命周期开始
一个对象的 __del__
方法一旦被调用,生命周期结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Student : def __init__ (self, name, age ): self.name = name self.age = age print (f"炼金术施展成功!{self.name} 已成功被初始化~" ) def __str__ (self ): return f"Student类对象,name:{self.name} , age:{self.age} " def __del__ (self ): print (f"啊!我{self.name} 要被销毁了~" ) stu = Student("阿贝多" , 24 ) print (stu)del stu
运算符重载 运算符重载 是指赋予基本运算符新的运算功能,使其能够应用于自定义类型的运算。
总览
魔法方法
说明
__add__(self, other)
加法运算 +
__sub__(self, other)
减法运算 -
__mul__(self, other)
乘法运算 *
__floordiv__(self, other)
浮点除法运算 //
__mod__(self, other)
取余运算 %
__pow__(self, other[, module]))
指数运算 **
__and__(self, other)
按位与运算 &
__xor__(self, other)
按位异或运算 ^
__or__(self, other)
按位或运算 |
__lt__(self, other)
比较操作符 <
__gt__(self, other)
比较操作符 >
__le__(self, other)
比较操作符 <=
__ge__(self, other)
比较操作符 >=
__eq__(self, other)
比较操作符 ==
__ne__(self, other)
比较操作符 !=
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Student : def __init__ (self, name, age ): self.name = name self.age = age def __lt__ (self, other ): return self.age < other.age def __le__ (self, other ): return self.age <= other.age def __eq__ (self, other ): return self.age == other.age stu1 = Student("神里绫华" , 19 ) stu2 = Student("神里绫人" , 23 ) print (stu1)print (stu1 == stu2)
封装 定义
封装 是将对象的变量(属性)和行为(方法)打包在一起,隐藏对象的内部 实现细节,只提供公开的接口(或方法)与外部交互 。
好处:
两步走:
将 属性 和 方法 封装 到一个抽象的 类 中
在类外 使用 类 创建 对象 ,然后让对象调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 class Gun : def __init__ (self, model ): self.model = model self.bullet_count = 0 def add_bullet (self, count ): self.bullet_count += count def shoot (self ): if self.bullet_count <= 0 : print ("没有子弹了..." ) return self.bullet_count -= 1 print (f"{self.model} 发射子弹~ [还剩{self.bullet_count} 颗]..." ) class Soldier : def __init__ (self, name ): self.name = name self.gun = None def fire (self ): if self.gun is None : print (f"{self.name} 还没有枪~" ) return print (f"冲啊{self.name} !" ) self.gun.add_bullet(50 ) for i in range (10 ): self.gun.shoot() ak47 = Gun("ak47" ) ak47.add_bullet(50 ) ak47.shoot() print ("-------------------" )xu3duo = Soldier("xu3duo" ) xu3duo.gun = Gun("M416" ) xu3duo.fire()
私有成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Girl : def __init__ (self, name ): self.name = name self.__age = 18 self.__weight = 125 def __weight (self ): print (f"{self.name} 的体重是{self.__weight} kg。" ) def scales (self ): print (f"{self.name} 的年龄是{self.__age} ,体重是{self.__weight} kg。" ) girl = Girl("小菲" ) print (girl.name) girl.__age = 17 print (girl.__age) """ Q:当我们尝试给私有变量赋值的时候,会发现不报错,打印时,输出也会正常输出,这是为什么呢? A:当你在外部执行 girl.__age = 17 时,Python并没有修改类中原来的 self.__age, 而是给对象 girl 添加了一个新的公共属性 __age,与原本私有的 __age 并无关系。 这就是为什么你可以通过 print(girl.__age) 输出结果。 """ print (girl._Girl__age) """ 在Python中,并没有真正意义的私有,私有属性和方法在内部会被 Python 自动改名为 _ClassName__attribute 的形式, 以避免外部直接访问。例如,在 Girl 类中,self.__age 实际上会被改写为 self._Girl__age。 所以我们可以通过 print(girl._Girl__age) 正常打印出我们在类内的赋值 18, 但是,在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法。 """ girl.scales()
继承 引例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class iPhone6 : IMEI = None producer = None def call_by_3g (self ): print ("3g通话" ) class iPhone16ProMax (iPhone6 ): face_id = True def call_by_5g (self ): print ("2024最新款" ) i16pm = iPhone16ProMax() i16pm.IMEI = "10001" i16pm.producer = "华强北" print (i16pm.IMEI)print (i16pm.producer)print (i16pm.face_id)i16pm.call_by_3g() i16pm.call_by_5g()
定义 继承是指在一个类中可以使用另一个类 中,已有的成员变量和成员方法 ,这样可以减少代码的重复性 ,方便代码的维护和更新 。
我们称继承类为派生类或子类(Derived class、Subclass) ,被继承的类称为基类、父类或超类 (Base class、Parent class、Super class)
子类可以继承父类所有的成员变量和成员方法,私有成员同样被继承,可以通过 _ClassName__attribute 的形式访问,但是不建议,所以我们默认子类继承了父类中的公共成员变量和公共成员方法,即非私有成员 。
单继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Animal : def __init__ (self, name ): self.name = name def eat (self ): return "eat" def drink (self ): return "drink" def sleep (self ): return "sleep" def run (self ): return "run" class Dog (Animal ): def bark (self ): return "bark" class Cat (Animal ): def meow (self ): return "meow" dog = Dog("Dundun" ) print (f"My name is {dog.name} , I can {dog.eat()} 、{dog.drink()} 、{dog.sleep()} 、{dog.run()} and {dog.bark()} ." )cat = Cat("Mimi" ) actions = f"{cat.eat()} 、{cat.drink()} 、{cat.sleep()} 、{cat.run()} and {cat.meow()} " print (f"My name is {cat.name} , I also can {actions} ." )
传递性 子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Animal : def __init__ (self, name ): self.name = name def eat (self ): return "eat" def drink (self ): return "drink" def sleep (self ): return "sleep" def run (self ): return "run" class Dog (Animal ): def bark (self ): return "bark" class Xiaotiandog (Dog ): def fly (self ): return "fly" xtd = Xiaotiandog("白犬神嗷" ) actions = f"{xtd.eat()} 、{xtd.drink()} 、{xtd.sleep()} 、{xtd.run()} and {xtd.bark()} " print (f"My name is {xtd.name} , not Only Can I {actions} , but I can also {xtd.fly()} !" )
多继承 子类 可以拥有 多个父类 ,并且具有 所有父类 的 属性 和 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Animal : def __init__ (self, name ): self.name = name def eat (self ): return "eat" def drink (self ): return "drink" def sleep (self ): return "sleep" def run (self ): return "run" class cattle (Animal ): def moo (self ): return "哞哞" class horse (Animal ): def neigh (self ): return "嘶嘶" class Niuma (cattle, horse): def ok (self ): return "收到!" nm = Niuma("牛马" ) print ("牛会哞马会叫,牛马会收到!" )print (nm.moo()) print (nm.neigh()) print (nm.ok())
多个父类 中,如果有同名的成员,那么默认以继承顺序(从左到右) 为优先级 。
即:先继承的保留,后继承的被覆盖
提示:在开发中,如果 父类之间 存在 同名的属性或者方法 ,应该 尽量避免 使用多继承。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class A : def show (self ): print ("A" ) class B (A ): def show (self ): print ("B" ) class C (A ): def show (self ): print ("C" ) class D (B, C): pass """ Q:class D(A, B, C)或者 class D(A, C, B)的写法是不被允许的,这是为什么? A:Python 的多重继承中,类的继承顺序要遵守 MRO(Method Resolution Order方法解析顺序)的规则, MRO使用C3线性化算法,C3算法的核心是merge()函数,这个函数的功能是遍历继承的父类,将每个父类看成一个序列, 如果一个序列的第一个元素,是其他序列中的第一个元素,或不在其他序列出现,就将其排到新列表中, 以这个class D(A, B, C)为例,我们有,序列1 [A]、序列2 [B, A](因为B继承了A)、序列3 [C, A]。 新列表中第一个应该是本身D,接着应该先放入B,因为A在其他序列出现,且不是在其他序列的第一个,其次放入C,最后放入A, 但是现在class D(A, B, C)排在第一个的A类,并不能符合MRO的规则,产生了冲突,所以就报错了。 """ d = D() d.show() print (D.__mro__)
__mro__
在搜索方法时,是按照 __mro__
的输出结果 从左至右 的顺序查找的,其中object
是 Python
为所有对象提供的 基类
如果在当前类中 找到方法,就直接执行,不再搜索
如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
如果找到最后一个类,还没有找到方法,程序报错
所以,慎用多继承。
复写(重写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Animal : id = "Animal" use_tools = False breathe = True feel_world = True def eat (self ): print ("吃东西" ) def drink (self ): return "山泉水" class Rabbit (Animal ): id = "Rabbit" def eat (self ): return "吃胡萝卜" def drink (self ): print (f"我要喝魔法兔子水,我的父类会喝{super ().drink()} 。" ) print (f"我要喝魔法兔子水,我的父类会喝{Animal.drink(self)} 。" ) class Person (Animal ): id = "Person" use_tools = True def eat (self ): return "吃预制菜" def id_show (self ): print (f"我的身份是 {self.id } " ) print (f"我的父类是 {super ().id } " ) print (f"我的父类是 {Animal.id } " ) r = Rabbit() print (f"兔子{r.eat()} ,会感受世界:{r.feel_world} ,还会使用工具:{r.use_tools} " )r.drink() print ("----------------------------------------------" )p = Person() print (f"人会{p.eat()} ,会感受世界:{p.feel_world} ,还会使用工具:{p.use_tools} " )p.id_show()
类型注解 定义 类型注解(Type Annotations)是 Python 的一种语法,用于在代码中标注变量、函数参数和返回值的类型 。这可以帮助开发者理解代码的意图,并且在一些开发工具和静态分析工具中提高代码的可读性和可维护性 。类型注解在 Python 3.5 引入,并在 Python 3.6 之后得到了进一步的完善。
变量注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import jsonimport randomvar_1 = random.randint(1 , 10 ) var_2 = json.loads('{"name": "LittleSugar"}' ) def func (): return 10 var_3 = func() var_4: int = "SpiderMan" var_5: str = 123 print (var_4, var_5)
注意:一般在无法直接看出变量类型 的时候,才会添加变量的类型注解 ,那种一眼就能看出来的显式类型一般都不用标注。
快捷键:把光标移到括号内,按 Ctrl + P 查看注解提示
函数注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def add (x: int , y: int ): return x + y a = add("a" , "dd" ) print (a)def func (data: list ) -> list : return data my_list = func(["a" , "b" ]) my_list.append("c" ) print (my_list)
Union 联合类型注解
1 2 3 4 5 6 7 8 9 from typing import Union my_list: list [Union [int , str ]] = [1 , 2 , "itmimi" , "itcat" ] def func (data: Union [int , str , list ] ) -> Union [int , str , list ]: return type (data) print (func(my_list))
多态 定义 多态是指在不同的类中实现相同的方法,而方法的行为会根据对象的类型不同而有所不同。它强调的是同一个接口,不同的实现 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Animal : def speak (self ): pass class Dog (Animal ): def speak (self ): print ("汪汪汪" ) class Cat (Animal ): def speak (self ): print ("喵喵喵" ) def make_sound (animal: Animal ): animal.speak() dog = Dog() cat = Cat() make_sound(dog) make_sound(cat)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class AC : def cool_wind (self ): """制冷""" pass def hot_wind (self ): """制热""" pass def swing_l_r (self ): """左右摆风""" pass class MideaAC (AC ): def cool_wind (self ): print ("美的空调制冷" ) def hot_wind (self ): print ("美的空调制热" ) def swing_l_r (self ): print ("美的空调左右摆风" ) class GreeAC (AC ): def cool_wind (self ): print ("格力空调制冷" ) def hot_wind (self ): print ("格力空调制热" ) def swing_l_r (self ): print ("格力空调左右摆风" ) def use_ac (ac: AC ): ac.cool_wind() ac.swing_l_r() midea_ac = MideaAC() gree_ac = GreeAC() use_ac(midea_ac) use_ac(gree_ac)
区别 :
多态 关注的是不同类之间,通过相同接口表现不同的行为,在 Python 中常通过继承和复写来实现动态多态。
复写 是子类重写父类的方法,改变父类已有的行为,子类可以通过 super()
来调用父类的版本,复写是实现多态的一种方式。
简言之,复写是实现多态的手段之一 ,而多态是一种通过接口统一实现不同行为的能力。
Python 数据分析案例 JSON JSON (JavaScript Object Notation,JavaScript 对象表示法)
优点:
Python 语言使用 JSON 有很大优势,因为:JSON 无非就是一个单独的字典或一个内部元素都是字典的列表
所以 JSON 可以直接和 Python 的字典或列表 进行无缝转换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import jsondata = [ {"name" : "张大山" , "age" : 11 }, {"name" : "王大锤" , "age" : 13 }, {"name" : "赵小虎" , "age" : 16 }, ] json_str = json.dumps(data, ensure_ascii=False ) """ 当 ensure_ascii 设置为 True(默认值)时,输出会确保将所有输入的非ASCII字符转义。 换句话说,它会将所有无法用ASCII表示的字符转换成对应的Unicode编码。 这样,经过 dumps 后的字符串中,汉字会变成以 \u 开头的Unicode编码. 当 ensure_ascii 设置为 False 时,这些字符会原样输出。 这意味着,如果你的数据中包含汉字,你应该设置 ensure_ascii=False,以便保留汉字而不是转义成Unicode编码。 """ print (type (json_str))print (json_str)d = {"name" : "周杰伦" , "addr" : "台北" } json_str = json.dumps(d, ensure_ascii=False ) print (type (json_str))print (json_str)s = '[{"name": "张大山", "age": 11}, {"name": "王大锤", "age": 13}, {"name": "赵小虎", "age": 16}]' l = json.loads(s) print (type (l))print (l)s = '{"name": "周杰伦", "addr": "台北"}' d = json.loads(s) print (type (d))print (d)
案例 data_define.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 """ 定义和数据相关的类 """ class Record : def __init__ (self, date, order_id, money, province ): self.date = date self.order_id = order_id self.money = money self.province = province def __str__ (self ): return f"{self.date} , {self.order_id} , {self.money} , {self.province} "
file_define.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 """ 定义和文件相关的类 """ import jsonfrom data_define import Recordclass 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(): line = line.strip() 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" ], data_dict["money" ], data_dict["province" ], ) record_list.append(record) f.close() return record_list if __name__ == "__main__" : text_file_reader = TextFileReader("D:/Desktop/Python/2011年1月销售数据.txt" ) json_file_reader = JsonFileReader("D:/Desktop/Python/2011年2月销售数据JSON.txt" ) list1 = text_file_reader.read_data() list2 = json_file_reader.read_data() for i in list1: print (i) for i in list2: print (i)
main.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 """ 面向对象,数据分析案例,主业务逻辑代码 实现步骤: 1. 设计一个类,可以完成数据的封装 2. 设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功能 3. 读取文件,生产数据对象 4. 进行数据需求的逻辑计算(计算每一天的销售额) 5. 通过PyEcharts进行图形绘制 """ from matplotlib import pyplot as pltfrom file_define import TextFileReader, JsonFileReaderfrom data_define import Recordtext_file_reader = TextFileReader("D:/Desktop/Python/2011年1月销售数据.txt" ) json_file_reader = JsonFileReader("D:/Desktop/Python/2011年2月销售数据JSON.txt" ) jan_data: list [Record] = text_file_reader.read_data() feb_data: list [Record] = json_file_reader.read_data() jan_data.extend(feb_data) data_dict = {} for record in jan_data: if record.date in data_dict.keys(): data_dict[record.date] += record.money else : data_dict[record.date] = record.money print (data_dict)x = list (data_dict.keys()) y = list (data_dict.values()) plt.rcParams["font.sans-serif" ] = ["SimHei" ] plt.rcParams["axes.unicode_minus" ] = False plt.figure(figsize=(12 , 6 )) plt.bar(x, y, color="#32a5d7" , label="销售额" ) plt.title("每日销售额" ) plt.xlabel("日期" ) plt.ylabel("销售额" ) plt.legend() plt.xticks(rotation=45 ) plt.show()
图片截取自:Spyder 6