类型 | 描述 |
---|---|
数字 | |
字符串 | 描述文本的一种数据类型 |
列表 | 有序的可变序列 |
元组 | 无序的不可变序列 |
集合 | 无序不重复集合 |
字典 | 无序的Key-Value集合 |
在程序代码中对程序代码进行解释说明的文字
作用:注释不是程序。不能被执行。只是对程序进行注释说明,增强可读性。
在程序运行时,能够存储计算结果或能表示值的抽象概念。
简单的说,变量就是在程序运行时,记录数据用的。
变量名 = 变量值
变量的值可以改变
直接输出类型信息,返回一个字符串。
变量没有类型,是变量存储的数据类型。
语句(函数) | 说明 |
---|---|
int(x) | 将x转换为一个整a数,将浮点数的小数部分删掉 |
float(x) | 将x转换为一个浮点数 |
str(x) | 将对象x转换为字符串 |
内容限定
标识符中,只可以出现:
大小写敏感
不可以使用关键字
注意
见名知意
下划线命名法
英文字母全小写
运算符 | 描述 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除,float |
// | 取整除,int |
% | 取余 |
** | 指数 |
三引号定义法,和多行注释的写法一样,同样支持换行操作。
使用变量接收他,他就是字符串。
不使用变量接收他,就可以作为多行注释使用。
如果定义字符串本身想包含单引号、双引号自身,可以:
可以通过+将两个字符串拼接,可以字面量+字面量,也可以变量+字面量、变量+变量
注意:只能适用于字符串本身,不能用于其他类型
name = "李明"
number = 19100
message = "名字是%s,电话是%s" % (name,number)
print(message)
其中的,%s
格式化符号 | 转化 |
---|---|
%s | 字符串 |
%d | 整型 |
%f | 浮点型 |
name = "李明"
age = 18
height = 1.78
message = "名字:%s,年龄:%d,身高:%f" % (name,age,height)
可以使用辅助符号“m.n”来控制数据的宽度和精度
通过语法:f"内容{变量}"的格式来快速格式化
name = "李明"
age = 18
height = 1.78
message = f"名字:{name},年龄:{age},身高:{height}"
f为format,格式化的符号,不关心类型和精度
表达式:一条具有明确执行结果的代码语句
print("1*1的结果是%d" % (1*1))
print(f"1*1的结果是{1*1}")
print("字符串在python中类型为%s" % type('字符串'))
使用input()语句从键盘获取输入,使用变量存储输入
print("输入名字")
name = input()
print("你是%s"%name)
输入的为字符串类型,可以通过类型转换改变数据类型。
定义变量存储布尔类型数据:
变量名称 = 布尔类型字面量
布尔类型的数据,不仅可以通过定义得到,也可以通过比较运算符进行内容比较得到。
运算符 | 描述 | 示例 |
---|---|---|
== | ||
!= | ||
> | ||
< | ||
>= | ||
<= |
if 要判断的条件:
条件成立时,要做的事情
通过缩进判断代码块属于哪一个if
if 条件:
满足条件做的事情
else:
不满足条件做的事情
if 条件1:
条件1满足时做的事情
elif 条件2:
条件2满足时做的事情
else:
所有条件都不满足时做的事情
判断互斥且是有顺序的:
if 条件1:
满足条件1做的事
if 条件2:
满足条件2做的事
嵌套的关键点在于缩进
通过缩进来决定语句之间的层次关系
while 条件:
条件满足做的事情
只要条件满足会无限执行
while 条件1:
条件1满足时做的事情
while 条件2:
条件2满足时做的事情
for 临时变量 in 待处理数据集:
循环满足条件时执行的代码
for循环语句,本质上是遍历:序列类型。
语法:
range(num1,num2,step)
获得一个从num1开始,到num2结束的数字序列,不含num2本身。
数字之间的步长,以step为准。
for 临时变量 in 待处理的数据集:
循环条件满足时应做的事情1
for 临时变量 in 待处理的数据集:
循环条件满足时应做的事情2
中断本次循环,直接进入下一次循环
直接结束循环
函数是组织好的,可重复使用的,用来实现特定功能的代码段
def 函数名(传入参数):
函数体
return 返回值
在函数进行计算的时候,接受外部(调用时)提供的数据
def add(x,y):
result = x+ y
return result
传入参数的个数不受限制,可以不使用参数,也可以使用任意N个参数
函数在执行完成后,返回给调用者的结果
def 函数名(传入参数):
函数体
return 返回值
变量 = 函数(参数)
函数在遇到return后就结束了,后面代码不执行
如果函数没有使用return语句返回数据,那么函数返回None。
None ,类型是
在if中,None等于False
通过多行注释的形式,写在函数体之前
指在一个函数里面又调用一个函数
函数a中执行到调用函数b的语句,会将函数b全部执行完后,继续执行a的剩余内容
变量的作用域指的是变量的作用范围
定义在函数体内部的变量,即只在函数体内部生效
作用:在函数体内部,临时保存数据,即当函数调用完成后,即销毁局部变量
指在函数体内,外都能生效的变量
使用global关键字,可以在函数内部声明变量为全局变量
def test_return():
return 1,2
x,y = test_return()
按照返回值的顺序,写对应顺序的多个变量接受即可
变量间用逗号隔开
支持不同类型的数据return
使用方式不同,函数有4种常见参数使用方式
调用函数时根据函数定义的参数位置来传递参数
def user_info(name,age,gender):
print(f"您的姓名是{name},年龄是{age},性别是{gender}")
user_info("tom",20,"男")
注意:传递的参数和定义的参数的顺序及个数必须一致
函数调用时通过“键=值”的形式传递参数
作用:可以让函数更加清晰,容易使用,同时也清除了参数的顺序需求
def user_info(name,age,gender):
print(f"您的姓名是{name},年龄是{age},性别是{gender}")
#关键字传参
user_info(name = "tom",age = 20,gender = "男")
#可以不按照固定顺序
user_info(age = 20,name = "tom",gender = "男")
#可以和位置参数混着用,但位置参数必须在前,且匹配参数顺序
user_info("tom",gender = "男",age = 20)
缺省参数也叫默认参数,对于定义函数,为参数提供默认值,调用函数时可以不传该默认参数的值,所有位置参数必须出现在默认参数之前,包括函数定义和调用。
作用:当调用函数时没有传递参数,就会使用默认是缺省参数对应的值
def user_info(name,age,gender = "男"):
print(f"您的姓名是{name},年龄是{age},性别是{gender}")
user_info("tom",20)
默认参数必须写在最后面
不定长参数也叫可变参数,用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
作用:当调用函数时不确定参数的个数,可以使用不定长参数
类型:
位置传递
def user_info(*args):
print(args)
user_info("tom",20)
传进的所有参数会被args变量收集,他会根据传进参数的位置合并为一个元组,args是元组类型,就是位置传递。
关键字传递
def user_info(**kwargs):
print(kwargs)
user_info(name = "tom",age = 20)
参数是“键=值”形势的情况下,所有的“键=值”都会被kwargs接受,同时会根据“键=值”形成字典
def test_func(compute):
result = compute(1,2)
return result
def compute(x,y):
return x+y
test_func(compute) #结果3
函数compute,作为参数,传入了test_func函数中使用
所以,这是一种,计算逻辑的传递,而非数据的传递
函数的定义中
有名称的函数,可以基于名称重复使用
无名称的匿名函数,只可以临时使用一次
语法
lambda 传入参数:函数体(一行代码)
def test_func(compute):
result = compute(1,2)
return result
test_func(lambda x,y :x+y) #结果3
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素,每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。
语法
#字面量
[元素1,元素2,....]
#定义变量
变量名称 = [元素1,元素2,....]
#定义空列表
变量名称 = []
变量名称 = list()
列表可以一次存储多个数据,也可以为不同数据类型,支持嵌套。
从0开始,依次递增,列表名[下标]。
反向索引,从-1开始,倒数第一个。
注意不要超出范围,否则会报错
功能:查找指定元素在列表的下标,如果找不到,报错ValueError
语法:
列表.index(元素)
功能:修改特定位置的元素值,对指定下标(正向、反向均可)的值进行重新赋值。
语法:
列表[下标] = 值
功能:在指定的下标位置,插入指定的元素
语法:
列表.insert(下标,元素)
追加元素1
功能:在列表尾部插入指定的元素
语法:
列表.append(元素)
追加元素2
功能:将其他数据容器的内容取出后,依次追加到列表尾部
语法:
列表.extend(其他数据容器)
del
功能:函数式删除
语法:
del 列表[下标]
pop
功能:列表的方法,将删除的元素返回
语法:
列表.pop[下标]
remove
功能:删除某元素在列表的第一个匹配项
语法:
列表.remove(元素)
功能:清空列表
语法:
列表.clear()
功能:统计列表中某元素的数量
语法:
列表.count(元素)
功能:统计列表中所有元素的数量
语法:
len(列表名)
将容器内的元素依次取出,并处理,称之为遍历操作
可以使用while循环和for循环操作
for 临时变量 in 数据容器:
对临时变量进行处理
#定义元组字面量
(元素1,元素2,元素3)
#定义元组变量
变量名称 = (元素1,元素2)
#定义空元组
变量名称 = ()
变量名称 = tuple()
查找某个数据,如果数据存在返回对应下标,否则报错
元组.index(元素)
统计某个数据在当前元组出现的次数
元组.count()
统计元组内的元素个数
len(元组)
从前向后,下标从0开始
从后向前,下标从-1开始
字符串是一个无法修改的数据容器
查找子串在原字符串中起始下标
字符串.index(子串)
将字符串内的全部:字符串1,替换为字符串2
不是修改字符串本身,而是得到了一个全新的字符串
字符串.replace(字符串1,字符串2)
按照指定的分割符字符串,将字符串划分为多个字符串,并存入列表对象中
字符串.split(分隔符字符串)
字符串本身不变,而是得到了一个列表对象
字符串的规整操作,去前后空格
字符串.strip()
去前后指定字符串
字符串.strip(字符串)
会将字符串变成字符去除
统计字符串内某个子串出现次数
字符串.count(字符串)
len(字符串)
包含空格
指的是内容连续、有序、可使用下标索引的一类数据容器
从一个序列中,取出一个子序列
序列[起始下标;结束下标;步长]
#定义集合字面量
{元素,元素,...,元素}
#定义集合变量
变量名称 = {元素,元素,...,元素}
#定义空集合
变量名称 = set()
集合.add()
集合.remove()
随机取一个元素并返回
集合.pop()
清空集合
集合.clear()
取两个集合的差集,集合1有而集合2没有,返回一个新的集合
集合1.difference(集合2)
对比集合1和集合2,在集合1中,删除和集合2相同的元素
结果,集合1被修改,集合2不变
集合1.difference_update(集合2)
将集合1和集合2合并,返回新集合,原集合不变
集合1.union(集合2)
统计集合元素数量
len(集合)
集合不支持下标,不能用while循环,可以用for循环
字典定义,同样使用{},不过存储的元素是一个个的:键值对
#定义字典字面量
{key:value,key:value,...,key:value}
#定义字典变量
my_dict = {key:value,key:value,...,key:value}
#定义空字典
my_dict = {}
my_dict = dict()
字典同集合一样,不可以使用下标索引
但是字典可以通过key值来取得对应的value
从字典中基于key获取value
字典[key]
字典的嵌套
字典中key和value可以是任何·数据类型(key不可以为字典)
字典[key] = value
字典[key] = value
字典里key不可以重复,如果不存在新key,则新增元素,否则修改元素
字典.pop(key)
获得指定key的value,同时字典被修改,指定key的数据被删除
字典.clear()
字典.keys()
得到字典全部的key,是dict_keys类型,可以for循环遍历
len(字典)
列表 | 元组 | 字符串 | 集合 | 字典 | |
---|---|---|---|---|---|
元素数量 | 支持多个 | 支持多个 | 支持多个 | 支持多个 | 支持多个 |
元素类型 | 任意 | 任意 | 仅字符 | 任意 | key:value(key:除字典外任意类型,value:任意类型) |
下标索引 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
重复元素 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
可修改性 | 支持 | 不支持 | 不支持 | 支持 | 支持 |
数据有序 | 是 | 是 | 是 | 否 | 否 |
使用场景 | 可修改的,可重复的一批数据记录场景 | 不可修改的,可重复的一批数据记录场景 | 一串字符的记录场景 | 不可重复的数据记录场景 | 以key检索value的数据记录场景 |
统计数据容器长度
找到数据容器中最大的元素
max(数据容器)
找到数据容器中最小的元素
min(数据容器)
sorted(数据容器,[reverse = True])
对内容排序,返回一个列表
reverse = True表示降序
编码分类
UTF-8是目前全球通用的编码格式
使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下
open(name,mode,encoding)
f = open('python.txt','r',encoding='UTF-8')
#encoding的顺序不是第三位,所以不能使用位置参数,用关键字参数直接指定
mode常用三种模式
模式 | 描述 |
---|---|
r | 以只读方式打开。文件袋指针将会放在文件的开头。这是默认模式 |
w | 打开一个文件只用于写入。如果文件已存在则打开文件,并从头开始编辑,原有内容会删除。如果文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果文件已存在,新的内容将会被写入到已有的内容之后。如果文件不存在,创建新文件进行写入。 |
文件对象.read(num)
num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。指针会移动。
f = open('python.txt')
content = f.readlines()
#['hello world\n','abcdefg\n','aaa\n','bbb\n','ccc']
print(content)
#关闭文件
f.close()
readlines可以按照行的方式把整个文件的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
一次读取一行内容
f = open('python.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
#关闭文件
f.close()
for循环读取文件行
for line in open("python.txt",'r')
print(line)
#每一个line临时变量,就记录了文件一行数据
f = open('python.txt')
f.close()
不关闭文件,文件一直占用
with open("python.txt",'r') as f:
for line in f:
print(line)
执行完语句后,文件自动关闭
#1.打开文件
f = open("python.txt",'w')
#2.文件写入
f.write('hello world') #写内存
#3.内容刷新
f.flush() #写硬盘
注意:
#1.打开文件
f = open("python.txt",'a')
#2.文件写入
f.write('hello world') #写内存
#3.内容刷新
f.flush() #写硬盘
注意:
当检错的一个错误时,python解释器就无法继续执行,反而出现一些错误的提示,就是异常,也叫bug
try:
可能发生错误的代码
except:
如果出现异常执行的代码
捕获指定的异常
try:
except NameError as e:
print('出现变量未定义的异常')
print(e)
捕获多个异常
try:
except (NameError,ZeroDivisionError) as e:
print('出现变量未定义的异常')
print(e)
捕获全部异常
try:
except Exception as e:
print('出现变量未定义的异常')
print(e)
else:
没有异常执行代码
finally:
最终执行代码
异常具有传递性。
def func1():
print('this is func1')
num = 1/0
print("func0 over")
def func2():
print("this is func2")
func1()
print('func2 over')
def main():
try:
func2()
except Exception as e:
print(e)
当函数func1中发生异常,并且没有捕获处理这个异常,异常会传递到func2,当func2也没有捕获处理这个异常的时候,main函数就会捕获这个异常,这就是异常的传递性。
一个模块就是一个工具包,每一个工具包都有各种不同的工具供我们使用进而实现各种不同的功能
[from 模块名] import [模块|类|变量|函数|*] [as 别名]
常用组合类型
当导入多个模块的时候,且模块内有同名功能,当调用这个同名功能时候,调用的是后面导入模块的功能。
**__main__**变量
if __name__ == '__main__':
执行模块代码
**__all__**变量
如果一个模块文件中有’__all__‘变量,当使用from xxx import * 导入时候,只能导入这个列表中的元素。没有all变量则导入全部。若想导入可以手动导入。
__all__ = ['test1']
def test1():
pass
def test2():
pass
从物理上看,包就是一个文件夹,在该文件夹下包含了一个__init__.py文件,该文件夹可用于包含多个模块文件
从逻辑上看,包的本质依然是模块
导入包
import 包名.模块名
在’__init__.py’文件中添加’__all__= []',控制允许导入的模块列表
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
定义
主要功能
json就是一种在各个编程语言中流通的数据格式,负责不同编程语言的数据交互和传递
#导包,导入line功能构建折线图对象
from pyecharts.charts import Line
#得到折线图对象
line = Line()
#添加x轴数据
line.add_xaxis(["中国","美国","英国"])
#添加Y轴数据
line.add_yaxis("gdp",[30,20,10])
#生成图标
line.render()
配置选项
全局配置选项可以通过set_global_opts方法来进行配置
set_global_opts方法
#导包,导入line功能构建折线图对象
from pyecharts.charts import Line
from pyecharts.options import TitleOpts,LegendOpts,ToolboxOpts,VisualMapOpts
#得到折线图对象
line = Line()
#添加x轴数据
line.add_xaxis(["中国","美国","英国"])
#添加Y轴数据
line.add_yaxis("gdp",[30,26,10])
#设置全局配置项
line.set_global_opts(
title_opts=TitleOpts(title="GDP展示",pos_left="center",pos_bottom="1%"),
legend_opts= LegendOpts(is_show=True),
toolbox_opts= ToolboxOpts(is_show=True),
visualmap_opts= VisualMapOpts(is_show=True)
)
#生成图标
line.render()
import json
from pyecharts.charts import Line
from pyecharts.options import TitleOpts,LabelOpts
#处理数据
f_us = open("美国.txt","r",encoding="UTF-8")
us_data = f_us.read()
f_jp = open("日本.txt","r",encoding="UTF-8")
jp_data = f_jp.read()
f_in = open("印度.txt","r",encoding="UTF-8")
in_data = f_in.read()
#去掉不合理的JSON规范的开头
us_data = us_data.replace("jsonp_1629344292311_69436(","")
jp_data = jp_data.replace("jsonp_1629350871167_29498(","")
in_data = in_data.replace("jsonp_1629350745930_63180(","")
#去掉不合理JSON数据规范的结尾
us_data = us_data[:-2]
jp_data = jp_data[:-2]
in_data = in_data[:-2]
#JSON转换为python字典对象
us_dict = json.loads(us_data)
jp_dict = json.loads(jp_data)
in_dict = json.loads(in_data)
#获取trend key
us_trend_data = us_dict["data"][0]["trend"]
jp_trend_data = jp_dict["data"][0]["trend"]
in_trend_data = in_dict["data"][0]["trend"]
#获取日期数据,用于x轴,取2020年(到314下标结束)
us_x_data = us_trend_data["updateDate"][:314]
jp_x_data = jp_trend_data["updateDate"][:314]
in_x_data = in_trend_data["updateDate"][:314]
#获取确诊数据,用于Y轴,取2020年(到下标314结束)
us_y_data = us_trend_data["list"][0]["data"][:314]
jp_y_data = jp_trend_data["list"][0]["data"][:314]
in_y_data = in_trend_data["list"][0]["data"][:314]
#生成图表
#构建折线图对象
line = Line()
#添加x轴数据,x轴是公用的,所以添加一个就可以
line.add_xaxis(us_x_data)
#添加y轴数据
line.add_yaxis("美国确诊人数",us_y_data,label_opts=LabelOpts(is_show=False)) #显示数字
line.add_yaxis("日本确诊人数",jp_y_data,label_opts=LabelOpts(is_show=False))
line.add_yaxis("印度确诊人数",in_y_data,label_opts=LabelOpts(is_show=False))
#设置全局选项
line.set_global_opts(
title_opts= TitleOpts(title="2020年美日印三国确诊人数对比折线图",pos_left="center",pos_bottom="1%")
)
#调用render方法,生成图标
line.render()
#关闭文件对象
f_us.close()
f_jp.close()
f_in.close()
import json
from pyecharts.charts import Map
from pyecharts.options import *
#读取文件数据
f = open("疫情.txt","r",encoding="UTF-8")
data = f.read()
#关闭文件
f.close()
#读取各省数据
#将字符串json转换为python字典
data_dict = json.loads(data)
#从字典读取各省数据
province_data_list = data_dict["areaTree"][0]["children"]
#组装每个省份和确诊人数为元组,并各个省的数据都封装入列表内
data_list = [] #绘图需要的数据列表
for province_data in province_data_list:
province_name = province_data["name"] #省份名称
if province_name in ["北京","天津","重庆","上海"]:
province_name = province_name + "市"
elif province_name in ["内蒙古","西藏"]:
province_name = province_name + "自治区"
elif province_name == "新疆":
province_name = province_name + "维吾尔自治区"
elif province_name == "宁夏":
province_name = province_name + "回族自治区"
elif province_name == "广西":
province_name = province_name + "壮族自治区"
else:
province_name = province_name + "省"
province_confirm = province_data["total"]["confirm"] #确诊人数
data_list.append((province_name,province_confirm))
#创建地图对象
map = Map()
#添加数据
map.add("各省份确诊人数",data_list,"china")
#设置全局选项
map.set_global_opts(
title_opts= TitleOpts(title="全国疫情地图"),
visualmap_opts= VisualMapOpts(
is_show=True,
is_piecewise=True,
pieces=[
{"min": 1, "max": 99, "lable": "1-99人", "color": "#CCFFFF"},
{"min": 100, "max": 999, "lable": "100-999人", "color": "#FFFF99"},
{"min": 1000, "max": 4999, "lable": "1000-4999人", "color": "#FF9966"},
{"min": 5000, "max": 9999, "lable": "5000-9999人", "color": "#FF6666"},
{"min": 10000, "max": 99999, "lable": "10000-99999人", "color": "#CC3333"},
{"min": 100000, "lable": "100000+", "color": "#990033"},
]
)
)
map.render("全国疫情地图.html")
import json
from pyecharts.charts import Map
from pyecharts.options import *
#读取文件数据
f = open("疫情.txt","r",encoding="UTF-8")
data = f.read()
#关闭文件
f.close()
#读取各省数据
#将字符串json转换为python字典
data_dict = json.loads(data)
#从字典读取河南数据
cities_data = data_dict["areaTree"][0]["children"][3]["children"]
#组装每个省份和确诊人数为元组,并各个省的数据都封装入列表内
data_list = [] #绘图需要的数据列表
for city_data in cities_data:
city_name = city_data["name"] + "市"
city_confirm = city_data["total"]["confirm"] #确诊人数
data_list.append((city_name,city_confirm))
data_list.append(("济源市",5))
#创建地图对象
map = Map()
#添加数据
map.add("河南省疫情分布",data_list,"河南")
#设置全局选项
map.set_global_opts(
title_opts= TitleOpts(title="河南省疫情地图"),
visualmap_opts= VisualMapOpts(
is_show=True,
is_piecewise=True,
pieces=[
{"min": 1, "max": 99, "lable": "1-99人", "color": "#CCFFFF"},
{"min": 100, "max": 999, "lable": "100-999人", "color": "#FFFF99"},
{"min": 1000, "max": 4999, "lable": "1000-4999人", "color": "#FF9966"},
{"min": 5000, "max": 9999, "lable": "5000-9999人", "color": "#FF6666"},
{"min": 10000, "max": 99999, "lable": "10000-99999人", "color": "#CC3333"},
{"min": 100000, "lable": "100000+", "color": "#990033"},
]
)
)
map.render("河南疫情地图.html")
from pyecharts.charts import Bar,Timeline
from pyecharts.options import *
from pyecharts.globals import ThemeType
bar1= Bar()
bar1.add_xaxis(['中国','美国','英国'])
bar1.add_yaxis("GDP",[30,30,10],label_opts=LabelOpts(
position="right"
))
bar1.reversal_axis()
bar2= Bar()
bar2.add_xaxis(['中国','美国','英国'])
bar2.add_yaxis("GDP",[30,20,40],label_opts=LabelOpts(
position="right"
))
bar2.reversal_axis()
bar3= Bar()
bar3.add_xaxis(['中国','美国','英国'])
bar3.add_yaxis("GDP",[50,60,70],label_opts=LabelOpts(
position="right"
))
bar3.reversal_axis()
timeline = Timeline(
{"theme": ThemeType.LIGHT}
)
timeline.add(bar1,"点1")
timeline.add(bar2,"点2")
timeline.add(bar3,"点3")
timeline.add_schema(
play_interval=1000,
is_timeline_show=True,
is_auto_play=True,
is_loop_play=True
)
timeline.render("基础时间线柱状图.html")
from pyecharts.charts import Bar,Timeline
from pyecharts.options import *
from pyecharts.globals import ThemeType
#读取数据
f = open('1960-2019全球GDP数据.csv','r',encoding='GB2312')
data_lines = f.readlines()
#关闭文件
f.close()
#删除第一条数据
data_lines.pop(0)
#将数据转换为字典存储
data_dict = {}
for line in data_lines:
year = int(line.split(',')[0])
country = line.split(',')[1]
gdp = float(line.split(',')[2])
#判断字典有没有key
try:
data_dict[year].append([country,gdp])
except KeyError:
data_dict[year] = []
data_dict[year].append([country,gdp])
#创建时间线对象
timeline = Timeline({"theme" : ThemeType.LIGHT})
#排序年份
sorted_year_list = sorted(data_dict.keys())
for year in sorted_year_list:
data_dict[year].sort(key=lambda element:element[1],reverse=True)
#取出本年份前8的国家
year_data = data_dict[year][0:8]
x_data = []
y_data = []
for country_gdp in year_data:
x_data.append(country_gdp[0])
y_data.append(country_gdp[1])
#构建柱状图
bar = Bar()
x_data.reverse()
y_data.reverse()
bar.add_xaxis(x_data)
bar.add_yaxis("GDP(亿)",y_data,label_opts=LabelOpts(position="right"))
#反转坐标轴
bar.reversal_axis()
#设置每一年标题
bar.set_global_opts(
title_opts=TitleOpts(title=f"{year}年全球前八GDP数据")
)
timeline.add(bar,str(year))
#设置自动播放
timeline.add_schema(
play_interval=1000,
is_timeline_show=True,
is_auto_play=True,
is_loop_play=True
)
timeline.render('1960-2019全球GDP前八.html')
定义类
class 类名称:
类的属性
类的行为
创建类对象的语法
对象 = 类名称()
成员方法的定义语法
def 方法名(self,形参1,形参2,....):
方法体
在定义方法的参数列表中,有一个self关键字必须填写:
self关键字尽管在参数列表总,但传参时可以忽略。
python类中可以使用**__init__()**方法,称之为构造方法
可以实现
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel
print("student创建一个类对象")
stu = Student("张三", 31, "1856666")
注意
内置方法也称之为魔术方法
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel
print("student创建一个类对象")
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age},tel:{self.tel}"
stu = Student("张三", 31, "1856666")
print(stu)
#student创建一个类对象
#Student类对象,name:张三,age:31,tel:1856666
当类对象需要被转换为字符串时,调用__str__(),会输出对象地址。可以自己设计转化字符串的行为
直接对两个对象进行比较是不可能的,但在类中实现__lt__方法,即可同时完成:小于符号和大于符号2种比较
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel
print("student创建一个类对象")
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age},tel:{self.tel}"
def __lt__(self, other):
return self.age < other.age
stu = Student("张三", 31, "1856666")
stu2 = Student('李四',25,'4566')
print(stu>stu2)
__le__()可用于:<=、>=两种比较运算符上
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel
print("student创建一个类对象")
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age},tel:{self.tel}"
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
stu = Student("张三", 31, "1856666")
stu2 = Student('李四',25,'4566')
print(stu<=stu2)
== 符号默认比较内存地址
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel
print("student创建一个类对象")
def __str__(self):
return f"Student类对象,name:{self.name},age:{self.age},tel:{self.tel}"
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
stu = Student("张三", 31, "1856666")
stu2 = Student('李四',31,'4566')
print(stu==stu2)
概念
将现实世界在类中描述属性和方法,即为封装。
类中提供私有成员的形式:
定义私有成员变量和私有成员方法,只需要:
以__(两个下划线)开头,即可完成设置
访问限制
类对象无法访问私有成员,类中其他成员可以访问私有
class Phone:
__current_voltage = 0.5 #当前运行电压
def __keep_single_core(self):
print("电量不足,让CPU单核运行")
def call_5g(self):
if self.__current_voltage >= 1:
print('5g已经打开')
else:
self.__keep_single_core()
p = Phone()
p.call_5g()
一个类继承另一个类
class Phone:
TMEI = None #序列号
Producer = None #厂商
def call_by_4g(self):
print('4g通话中')
class Phone2022(Phone):
face_id = True #面部识别
def call_by_5g(self):
print('2022最新5g通话')
p = Phone2022()
p.call_by_4g()
一个类继承多个类,按照从左向右顺序继承
class Phone:
TMEI = None #序列号
Producer = None #厂商
def call_by_4g(self):
print('4g通话中')
class NFC:
nfc_type = '第五代'
producer = 'HM'
def reader(self):
print('NFC读卡')
def writer(self):
print('NFC写卡')
class RemoteControl:
rc_type = '红外遥控'
def control(self):
print('红外打开')
class myphone(Phone,NFC,RemoteControl):
pass
p = myphone()
p.call_by_4g()
p.reader()
p.control()
pass表示空,用处是保证完整性。
多继承中,遇到同名的成员属性和成员方法,按照谁先继承谁优先级最高的顺序。
子类继承父类的成员属性和成员方法后,如果不满意,可以进行复写
即在子类中重新定义同名的属性和方法即可。
class Phone:
TMEI = None #序列号
Producer = None #厂商
def call_by_5g(self):
print('5g通话中')
class myphone(Phone):
producer = 'itcast'
def call_by_5g(self):
print('打开5g')
print('关闭CPU')
p = myphone()
p.call_by_5g()
调用父类同名成员
调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
使用super()调用父类成员
class Phone:
TMEI = None #序列号
Producer = 'ITCAST' #厂商
def call_by_5g(self):
print('5g通话中')
class myphone(Phone):
producer = 'ITHIEMA'
def call_by_5g(self):
print('打开5g')
#方式1
print(f'父类厂商{Phone.Producer}')
Phone.call_by_5g(self) #需要传入self
#方式2
print(f'父类厂商{super().Producer}')
super().call_by_5g()
print('关闭CPU')
p = myphone()
p.call_by_5g()
支持
为变量设置类型注解
基础语法:变量:类型
var_1: int = 10
var_2: float = 3.1415
var_3: bool = True
var_4: str = 'hello'
基础容器类型注解
my_list: list = [1,2,3]
my_tuple: tuple = (1,2,3)
my_set: set = {1,2,3}
my_dict: dict = {key:value}
my_str: str = 'hello'
容器类型详细注解
在python3.9直接注解,3.7版本需要导入包
from __future__ import annotations
my_list:list[int] = [1,2,3]
my_tuple:tuple[str,int,bool] = ('hello',66,True)
my_set:set[int] = {1,2,3}
my_dict:dict[str,int] = {key:value}
注意:
除了使用变量:类型这种语法做注解外,也可以在注释中进行类型注解
语法
#type: 类型
class Student:
pass
var_1 = random.randint(1,10) #type:int
var_2 = json.loads(data) #type:dict[str,int]
类型注解的限制
类型注解只是提示性的,并非决定性的。数据类型和注解类型无法对应也不会导致错误
对形参进行类型注解
def add(x:int,y:int):
return x+y
对返回值进行类型注解
def func(data:list) -> list:
return data
可以定义联合类型注解
from __future__ import annotations
from typing import Union
mylist:list[Union[str,int]] = [1,2,'hell']
可以对变量进行类型注解,同时也可以对返回值注解
from __future__ import annotations
from typing import Union
my_list:list[Union[int,str]] = [1,2,'hello']
def func(data:Union[int,str]) -> Union[int,str]:
pass
func()
多态,指的是:多种状态,即完成某个行为时,使用不同的对象会得到不同的状态
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.speak()
dog = Dog()
cat = Cat()
make_noise(dog)
make_noise(cat)
抽象类(接口)
设计的含义:
这种写法称之为抽象类
main
'''
面向对象,数据分析案例,主业务逻辑代码
实现步骤:
1.设计一个类,可以完成数据的封装
2.设计一个抽象类,定义文件读取的相关功能,并使用子类实现具体功能
3.读取文件,生产数据对象
4.进行数据需求的逻辑计算(计算每一天的销售额)
5.通过pyecharts进行图形绘制
'''
from __future__ import annotations
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
text_file_reader = TextFileReader('2011年1月销售数据.txt')
json_file_reader = JSONFileReader('2011年2月销售数据JSON.txt')
jan_data:list[Record] = text_file_reader.read_data()
feb_data:list[Record] = json_file_reader.read_data()
#将2个月份的数据合并为一个list来存储
all_date:list[Record] = jan_data + feb_data
#开始数据计算
data_dict = {}
for record in all_date:
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.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")
file_define
'''
和文件相关的类定义
'''
from __future__ import annotations
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():
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'],int(data_dict['money']),data_dict['province'])
record_list.append(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)
data_define
'''
数据定义的类
'''
from __future__ import annotations
class Record:
def __init__(self,date:str,order_id:str,money:int,province:str):
self.date = date #订单日期
self.order_id = order_id #订单id
self.money = money #订单金额
self.province = province #订单省份
def __str__(self):
return f"{self.date},{self.order_id},{self.money},{self.province}"
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称之为闭包。
def outer(logo):
def inner(msg):
print(f"<{logo}><{msg}><{logo}>")
return inner
fn1 = outer('hello')
fn1('world')
fn2 = outer('nihao')
fn2('we')
如果在闭包中内部修改外部函数的值,需要使用nonlocal关键字修饰外部函数的变量才可以在内部函数中修改它
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(10)
fn(20)
使用闭包实现ATM取钱
def account_creat(initial_amount = 0):
def atm(num,deposit = True):
nonlocal initial_amount
if deposit:
initial_amount += num
print(f"存款,+{num},账户余额,{initial_amount}")
else:
initial_amount -= num
print(f"取款,-{num},账户余额,{initial_amount}")
return atm
atm = account_creat()
atm(100)
atm(200)
atm(150,deposit=False)
优点:
缺点:
装饰器实际上也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
一般写法
def outer(func):
def inner():
print('我睡觉了')
func()
print('我起床了')
return inner
def sleep():
import random
import time
print('睡眠中....')
time.sleep(random.randint(1,5))
fn = outer(sleep)
fn()
快捷写法
def outer(func):
def inner():
print('我睡觉了')
func()
print('我起床了')
return inner
@outer
def sleep():
import random
import time
print('睡眠中....')
time.sleep(random.randint(1,5))
sleep()
设计模式是一种编程套路,可以极大的方便程序的开发
最常见、最经典的设计模式,就是面向对象
除了面向对象外,还有其他设计模式:
创建类的实例后,就可以得到一个完整的、独立的类对象
某些场景下,我们需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例以节省创建类对象的开销和内存开销
比如某些工具类,仅需要一个实例,即可在各处使用
这就是单例模式达到的效果
单例模式(singleton Patern)是一种常见的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
StrTools.py
class StrTools:
pass
str_tool = StrTools()
test.py
from StrTools import str_tool
s1 = str_tool
s2 = str_tool
print(id(s1))
print(id(s2))
当需要大量创建一个类的实例的时候,就可以使用工厂模式。
即,从原生的使用类的构造去创建对象的形式
迁移到,基于工厂提供的方法去创建对象的形式。
class Person():
pass
class Woorker(Person):
pass
class Student(Person):
pass
class Teacher(Person):
pass
class PersonFactory:
def get_person(self,p_type):
if p_type == 'w':
return Woorker()
elif p_type == "s":
return Student()
else:
return Teacher()
pf = PersonFactory()
worker = pf.get_person('w')
stu = pf.get_person('s')
teacher = pf.get_person('t')
好处
进程:就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程ID方便系统管理
线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位
操作系统中可以运行多个进程,即多任务运行
一个进程内可以运行多个线程,即多线程运行
注意
进程之间是内存隔离的,即不同的进程拥有各自的内存空间。
线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间。
并行执行
指的是同一时间做不同的工作。
进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行。
除了进程外,线程也是可以并行执行的。
import threading
thread_obj = threading.Thread([group [, target [, name [, args [, kwargs]]]]])
- group:暂时无用,未来功能的预留参数
- target:执行的目标任务名
- args:以元组的方式给执行任务传参
- kwargs:以字典方式给执行任务传参
- name:线程名,一般不用设置
import time
import threading
def sing(msg):
while True:
print(msg)
time.sleep(1)
def dance(msg):
while True:
print(msg)
time.sleep(1)
if __name__ == '__main__':
sing_therd= threading.Thread(target=sing,args=("我在唱歌,啦啦啦",))
dance_therd = threading.Thread(target=dance,kwargs={"msg":"我在跳舞,呱呱呱"})
sing_therd.start()
dance_therd.start()
Socket
socket(简称 套接字)是进程之间通信的一个工具,进程之间想要进行网络通信需要socket
Socket服务端:等待其他进程的连接、可接受发来的消息、可以回复消息
Socket客户端:主动连接服务端、可以发送消息、可以回复消息
服务端
'''
演示socket服务端开发
'''
#1.创建socket对象
import socket
socket_server = socket.socket()
#2.绑定ip地址和端口
socket_server.bind(('localhost',8888))
#3.监听端口
socket_server.listen(1)
#listen方法内接受一个整数传参数,表示接受的连接数量
#4.等待客户端连接
coon, address = socket_server.accept() #coon表示连接对象,address表示客户端地址信息
#accept()是一个阻塞方法,等待客户端的连接,如果没有连接,就卡在一行不向下执行
print(f"接收到客户端信息{address}")
while True:
#5.接受客户端信息,使用客户端和服务端的本次连接对象而非socket_server对象
data = coon.recv(1024).decode('UTF-8')
#recv()方法的返回值是一个字节数组也就是bytes对象,不是字符串,可以通过decode方法通过UTF-8将字节数据转化为字符串对象
print(f"客户端信息为{data}")
#6.发送回复消息
msg = input("请输入你和客户端回复的消息:")
if msg == 'exit':
break
coon.send(msg.encode('UTF-8'))
#7.关闭连接
coon.close()
socket_server.close()
客户端
'''
演示socket客户端
'''
#1.创建socket对象
import socket
socket_client = socket.socket()
#2.连接到服务器
socket_client.connect(("localhost",8888))
#3.发送消息
while True:
msg = input("请输入要给服务端发送的消息:")
if msg == 'exit':
break
socket_client.send(msg.encode("UTF-8"))
#4.接受返回信息
recv_data = socket_client.recv(1024)
print(f"服务端回复消息为{recv_data.decode('UTF-8')}")
#5.关闭连接
socket_client.close()
正则表达式,又称规则表达式,是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。
re.match(匹配规则,被匹配字符串)
从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配信息),匹配不成功返回空
re.search(匹配规则,被匹配字符串)
搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后。整个字符串找不到返回空。
findall(匹配规则,被匹配字符串)
匹配整个字符串,找出全部匹配项。找不到返回空list
import re
#match从头匹配
s = 'python itheima python itheima '
result = re.match('python',s)
print(result)
#search搜索匹配
res = re.search("python",s)
print(res)
#findall搜索全部匹配
ress = re.findall("python",s)
print(ress)
单字符匹配
字符 | 功能 |
---|---|
. | 匹配任意1个字符(\n),\.匹配自身 |
[] | 匹配[]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字 |
\s | 匹配空白,即空格、tab键 |
\S | 匹配非空白 |
\w | 匹配单词字符,即a-z、A-Z、0-9、_ |
\W | 匹配非单词字符 |
数量匹配
字符 | 功能 |
---|---|
* | 匹配前一个规则的字符出现0次或无数次 |
+ | 匹配前一个规则的字符出现1次或无数次 |
? | 匹配前一个规则的字符出现0次或1次 |
{m} | 匹配前一个规则的字符出现m次 |
{m,} | 匹配前一个规则的字符最少出现m次 |
{m,n} | 匹配前一个规则的字符出现m到n次 |
边界匹配
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词边界 |
分组匹配
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
() | 将括号中字符作为一个分组 |
案例
匹配账号,只能由字母和数字组成,长度限制6到10位
r = '^[0-9a-zA-Z]{6,10}$'
匹配QQ号,要求纯数字,长度5-11位,第一位不为0
r = '^[1-9][0-9]{4,10}$'
匹配邮箱地址,只允许QQ、163、gmail这三种邮箱地址
r = '^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$'
即方法自己调用自己的一种特殊写法
注意
os模块的三个方法
案例
找到目录下所有文件
'''
演示递归操作
需求:通过递归,找到一个指定文件夹的全部文件
思路:写一个函数,列出文件夹内全部内容,如果是文件就收集到list
如果是文件夹,就递归调用自己,再次判断
'''
import os
def get_files_recursion_from_dir(path):
'''
从指定的文件夹中使用递归的方式,获取全部的文件列表
:param path: 被判断的文件夹
:return: list,包含全部的文件,如果目录不存在或者无文件就返回一个空list
'''
file_list = []
if os.path.exists(path):
for f in os.listdir(path):
new_path = path + "/" + f
if os.path.isdir(new_path):
#进入这里表明这个目录是文件夹
file_list += get_files_recursion_from_dir(new_path)
else:
file_list.append(new_path)
else:
print(f"指定的目录{path},不存在")
return []
return file_list
print(get_files_recursion_from_dir("D:/DownLoad"))