Python 第1阶段编程笔记

python 第1阶段

第一章 你好python

初识python

python的起源

1989-吉多范罗苏姆构建了python的雏形

1991-第一个python解释器程序诞生

python名字-来自于吉多范罗苏姆喜爱的电视:Monty python’s flying crisis

为什么选择python

优雅:简单、易学、开发效率高

适用面非常广泛

什么是编程语言

**概念:**人类和计算机交流的一种专有领域语言

**工作原理:**将人类的想法,翻译成计算机可以识别的二进制,让计算机工作

python安装

第一个python程序

print("hello world")

**PS:**标点符号一定是英文的符号

常见问题

命令提示符:快捷键:win + r - 输入cmd

python解释器

计算机只认识0和1的二进制

解释器的作用:

1.将python代码翻译成计算机能够识别的二进制代码

2.解释器会将翻译的二进制提交给计算机去执行

.py 文件-----python语言的代码文件,里面记录的python的代码

python的开发环境

IDE工具PyCharm—开发者使用最多的开发工具

常用快捷键

  • ctrl + alt + s :打开软件设置
  • ctrl + d :复制当前行代码
  • shift + alt + 上\下 :将当前行代码上移或下移
  • crtl + shift + f10 :运行当前代码文件
  • shift + f6 :重命名文件
  • ctrl + a :全选
  • ctrl + c\v\x :复制、粘贴、剪切
  • ctrl + f :搜索

第二章 基础语法

字面量

**概念:**在代码中,被写下来的固定的值,称为字面量

**常用的值类型:**python中常用的有6种数据类型

类型描述说明
数字number整数int例:10,-10
浮点数float例:13.14,-3.14
复数complex例:4i+3j
布尔bool生活中的逻辑真和假,true (1)和false (0)
字符串string描述文本的一种数据类型由任意数量的字符组成,如中文、英文、各类符号、数字组成等。
列表list有序的可变序列python中使用最频繁的数据类型,可有序记录一堆数据
元组tuple有序的不可变序列可有序记录一堆不可变的python数据集合
集合set无序不重复集合可有序记录一堆不重复的python数据集合
字典dictionary无序key-value集合可无序记录一堆key-value 型的python 数据集合

PS:在python中字符串需要用双引号(" ")包围起来

注释

**注释:**在程序代码中对程序代码进行解释说明的文字。

**作用:**注释不是程序,不能被执行,只是对程序代码进行解释说明,让别人可以看懂程序代码的作用,能够增强代码的可读性。

  • **单行注释:**以 #开头,#右边 的所有文字当作说明,而不是真正要执行的程序,起辅助说明作用
# 单行注释

PS:#号和注释内容一般建议以一个空格隔开

  • 多行注释:一对三个引号 引起来(”““注释内容”“”**)来解释说明一段代码的作用使用方法
""" 
	多行注释
	多行注释
"""

变量

**变量:**在程序运行时,能存储计算结果或能表示值的抽象概念。

**变量的定义格式:**变量名称 = 变量的值

**变量的特征:**变量的值可以改变

money = 50
print("钱包还有:", money)
money = money - 10
print("买了东西花了10元,钱包还有:", money,"元")
  • print语句输出多份内容
print(内容1,内容2,···,内容N)

数据类型

目前入门阶段,主要接触三种数据类型:string、int、float

可以通过 type() 语句来得到数据的类型, 语法: type( 被查看类型的数据 )

type()语句的使用方式:

#1.在print语句中,直接输出类型信息:
print(type("小黑"))
print(type(666))
print(type(3.14))

#2.用变量存储type()的结果(返回值):
string_type = type("小黑")
int_type = type(666)
float_type = type(3.14)
print(string_type)
print(int_type)
print(float_type)

#3.使用type()语句,查看变量中存储的数据类型信息
name = "小黑"
name_type = type(name)
print(name_type)

我们通过type(变量)可以输出类型,查看的是:变量存储的数据的类型。(因为:变量无类型,但是它存储的数据有。)

**PS:**字符串变量表示变量存储了字符串,而不是表示变量就是字符串

数据类型转换

**数据类型转换的原因:**在特定的场景下,是可以相互转换的,如字符串转数字、数字转字符串等。

常见的转换语句

语句(函数)说明
int(x)将x转换为一个整数
float(x)将x转换为一个浮点数
str(x)将对象x转换为字符串

**PS:**三个语句都是带有返回值的语句。

# 将数字类型转换成字符串
num_str = str(11)
print(type(num_str),num_str)

float_str = str(3.14)
print(type(float_str),float_str)

# 将字符串转换成数字
num = int("11")
print(type(num),num)

num2 = float("3.14")
print(type(num2),num2)

#错误示例,想要将字符串转换成数字,必须要求字符串的内容都是数字
#num3 = int("小黑")
#print(type(num3),num3)

#整数转浮点数
float_num = float(11)
print(type(float_num),float_num)

#浮点数转整数
int_num = int(3.14)
print(type(int_num),int_num)

**PS:**任何类型都可以转换成字符串,但是字符串不能随意转换成数字(字符串里必须只有数字才可以)

标识符

**标识符:**是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名。比如:变量的名字、方法的名字、类的名字等等。

python中,标识符命名的规则主要有3类:内容限定、大小写限定、不可以使用关键字。

**1.内容限定:**标识符命名中只允许出现英文、中文、数字、下划线(_)。其余内容都不被允许。

注意:a.不推荐使用中文。 b.数字不可以开头。

**2.大小写限定:**字母大小写是完全能够区分的,一一对应。

**3.不可以使用关键字:**python中有一系列单词,称为关键字,关键字有其特定用途。

# 规则1:内容限定,限定只能使用:中文、英文、数字、下划线,注意:不能以数字开头
# 1_name = "张三"  #错误示例,不能以数字开头
# name_! = "张三" #错误示例 ,不能有!号
name_ = "张三"
_name = "张三"
name_1 = "张三"

# 规则2:大小写敏感
Abc = "Abc"
abc = "666"
print(Abc)
print(abc)

# 规则3:不可以使用关键字
# class = 1 #错误示例,使用了关键字class
# def = 1 #错误示例
Class = 1

变量命名规范:见名知意、下划线命名法、英文字母全小写

**见名知意:**明了(尽量做到,看到名字,就知道是什么意思),简洁(尽量在确保”明了“的前提下,减少名字的长度)

**下划线命名法:**多个单词组合变量名,要使用下划线做分隔

**英文字母全小写:**命名变量中的英文字母,应全部小写

运算符

算术(数字)运算符:+加、-减、*乘、/除、//取整除、%取余、**指数

# 算术(数字)运算符
print("1+1=",1+1)
print("2-1=",2-1)
print("3*3=",3*3)
print("4/2=",4/2)
print("11//2=",11//2)
print("9%2=",9%2)
print("2**2=",2**2)

**赋值运算符 “=”:**把 = 号右边的结果 赋给 左边的变量,如 num = 1+2*3,结果num的值为7

# 赋值运算符
num = 1 + 2 * 3

复合赋值运算符:

运算符描述实例
+=加法赋值运算符c+=a等效于c=c+a
-=减法赋值运算符c-=a等效于c=c-a
*=乘法赋值运算符c*=a等效于c=c*a
/=除法赋值运算符c/=a等效于c=c/a
%=取模赋值运算符c%=a等效于c=c%a
**=幂赋值运算符c**=a等效于c=c**a
//=取整除赋值运算符c//=a等效于c=c//a
# 复合赋值运算符
num = 1
num += 1 # num = num+1
print("num += 1:",num)
num -= 1
print("num -= 1:",num)
num *= 4
print("num *= 4:",num)
num /= 2
print("num /= 2:",num)
num = 3
num %=2
print("num %= 2:",num)
num **= 2
print("num **= 2:",num)
num = 9
num //= 2
print("num //= 2:",num)

字符串扩展

字符串的三种定义方式

1.单引号定义法:name = '小黑'

2.双引号定义法:name = "小黑"

3.三引号定义法:name = """小黑"""

三引号定义法,和多行注释的写法一样,同样支持换行操作。

使用变量接收它,它就是字符串

不使用变量接收它,就可以作为多行注释使用

# 单引号定义法:
name = '小黑'
print(type(name))
# 双引号定义法:
name = "小黑"
print(type(name))
# 三引号定义法:写法和多行注释一样
name = """
小
黑
"""
print(type(name))

**字符串的引号嵌套:**定义的字符串本身,是包含:单引号、双引号自身方式

  • 单引号定义法,可以内含双引号
  • 双引号定义法,可以内含单引号
  • 可以使用转义字符(\)来将引号解除效用,变成普通字符串
# 在字符串内包含双引号
name = '"小黑”'
print(name)
# 在字符串内包含单引号
name = "'小黑'"
print(name)
# 使用转义字符 \ 解除引号的效用
name = "\"小黑\""
print(name)
name = '\'小黑\''
print(name)
字符串拼接

如果我们有两个字符串(文本)字面量,可以将其拼接成一个字符串,通过 + 号即可完成,如:print("小"+"黑")

输出结果:小黑

一般,字面量和变量或变量和变量之间会使用拼接,如:

name = "小黑" print("我的名字是:" + name + ",我是学生")

输出结果:我的名字是小黑,我是学生

# 字符串字面量之间的拼接
print("小"+"黑")
# 字符串字面量和字符串变量的拼接
name = "小黑"
tel = 123456
print("我是:" + name + ",我是学生" + ",我的电话是:" + tel)# 代码运行错误,无法和非字符串类型的tel进行拼接

**PS:**无法和非字符串类型进行拼接

字符串格式化

可以通过如下语法,完成字符串和变量的快速拼接

name = "Lee"

message = "I am %s" % name

print(message)

其中的,%s

  • %表示:我要占位
  • s 表示:将变量变成字符串放入占位的地方

所以,综合起来的意思就是:我先占个位置,等一会有个变量过来,我把它变成字符串放到占位的位置

# 通过占位的形式,完成拼接
name = "Lee"
identity = "student"
message = "%s is a %s" % (name,identity)
print(message)
# 通过占位的形式完成数字和字符串的拼接
age = 18
number = 123
message = "%s is a %s , age = %s , number = %s" % (name,identity,age,number)
print(message)# 这里是将数字转换成了字符串

python中常用的数据类型占位很多,常用的有以下三类:

格式符号转化
%s将内容转换成字符串,放入占位位置
%d将内容转换成整数,放入占位位置
%f将内容转换成浮点型,放入占位位置
# 完成字符串、整数、浮点数,三种不同类型变量的占位
name = "Lee"
number = 37
score = 99.99
message = "I am %s,number = %d,score = %f"%(name,number,score)
print(message)
格式化的精度控制

我们可以使用辅助符号“m.n”来控制数据的宽度和精度

  • m,控制宽度,要求是数字(很少使用),设置的宽度小于数字自身,不生效
  • .n,控制小数点精度,要求是数字,会进行小数的四舍五入

示例:

  • %5d:表示将整数的宽度控制在5位,如数字11,被设置为5d,就会变成:[空格][空格][空格]11,用三个空格补足宽度。
  • %5.2f:表示将宽度控制为5,将小数点精度设置为2,小数点和小数部分也算入宽度计算。如11.345设置为%7.2f后,结果是:[空格][空格]11.35。两个空格补足宽度,小数部分限制2位精度后,四舍五入为 .35
  • %.2f:表示不限制宽度,只设置小数点精度为2,如11.345设置%.2f后,结果是:11.35
# 格式化的精度控制
num1 = 11
num2 = 11.345
print("数字11宽度限制为5,结果是:%5d"%num1)
print("数字11宽度限制为1,结果是:%1d"%num1) # m比数字本身宽度还要小,m不生效
print("数字11.345宽度限制为7,小数精度2,结果是:%7.2f"%num2) # 对小数部分做四舍五入
print("数字11.345宽度不限制,小数精度2,结果是:%.2f"%num2)

**PS:**如果m比数字本身宽度还要小,则m不生效;n会对小数部分做精度限制的同时,会对小数部分做四舍五入

字符串格式化方式 -快速写法

通过**语法:f"内容{变量}"**的格式来快速格式化

# 第二种字符串格式化的方式:f"{占位}"
name = "Lee"
number = 37
score = 99.99
print(f"I am {name},number = {number},score = {score}")

**PS:**这种方式不管数据类型,不做精度控制,适合对精度没有要求的时候快速使用

对表达式进行格式化

**表达式:**一条具有明确执行结果的代码语句

如:1+1、5*2,就是表达式,因为有具体结果,结果是一个数字

或者,常见的变量定义:

name = “Lee” 、age = 11+11

等号右侧的都是表达式,因为他们有具体的结果,结果赋值给了等号左侧的变量

# 对表达式进行字符串格式化
print("1*1的结果是:%d"%(1*1))
print(f"1*2的结果是:{1*2}")
print("字符串在python中的类型名是:%s"%type("字符串"))

**PS:**在无需使用变量进行数据存储的时候,可以直接格式化表达式,简化代码

如何格式化表达式?

  • f"(表达式)"
  • "%s\%d\%f"%(表达式,表达式,表达式)

**练习:**股价计算小程序

定义如下变量:

  • name,公司名

  • stock_price,当前股价

  • stock_code,股票代码

  • stock_price_daily_growth_factor,股票每日增长系数,浮点数类型,比如1.2

  • growth_days,增长天数

计算经过growth_days天的增长后,股价达到了多少钱

使用字符串格式化进行输出,如果是浮点数,要求小数点精度到2位数

# 股价计算小程序
name = "APPLE"
stock_price = 19.99
stock_code = "001101"
stock_price_daily_growth_factor = 1.2
growth_days = 7
finally_stock_price = stock_price*stock_price_daily_growth_factor**growth_days
print(f"公司:{name},股票代码:{stock_code},当前股价:{stock_price},")
print("每日增长系数:%.1f,经过%d天后,股价达到了:"
      "%.2f"%(stock_price_daily_growth_factor,growth_days,finally_stock_price))

数据输入

input()语句(函数)

在python中,input()语句用来获取键盘输入

  • 数据输出:print
  • 数据输入:input

使用方法:

  • 使用input()语句可以从键盘获取输入
  • 使用一个变量接收(存储)input()语句获取的键盘输入数据即可
# input()语句
print("Please tell me your name.")
name = input()
print("I know,you are %s"%name)

在前面的代码中,输出”Please tell me your name.“的语句其实是多余的

input()语句其实可以在要求使用者输入内容之前,输出提示内容的,方式:input(提示信息)

# input()语句
name = input("Please tell me your name.")
print("Get! You are %s"%name)
# 输入数字类型
num = input("What is your ID?")
# 数据类型转换
num = int(num)
print("OK,输入数据类型是:",type(num))
# input语句默认全部当字符串看待,变成整型需要数据类型转换

**PS:**无论键盘输入什么数据类型,获取到的数据永远都是字符串类型

**练习:**欢迎登录小程序

# 欢迎登录小程序
#定义两个变量,用以获取从键盘输入的内容,并给出提示信息:
#变量1,变量名:user_name,记录用户名称
#变量2,变量名:user_type,记录用户类型
#并通过格式化字符串的形式,通过print语句输出欢迎信息
user_name = input("your name")
user_type = input("your type")
print(f"{user_type} {user_name},welcome!")

第三章 判断语句

**前言:**进行逻辑判断,是生活中常见的行为。同样,在程序中,进行逻辑判断也是最为基础的功能。

布尔类型和比较运算符

进行判断,只有2个结果:

布尔类型的定义

布尔类型的字面量:

  • True 表示真(是、肯定)
  • False表示假(否、否定)

定义变量存储布尔类型数据:变量名称 = 布尔类型字面量

**比较运算符:**布尔类型的数据,不仅可以通过定义得到,也可以通过比较运算符进行内容比较得到。

运算符术语示例结果
==相等于4==30
!=不等于4!=31
<小于4<30
>大于4>31
<=小于等于4<=30
>=大于等于4>=11
# 布尔类型的定义
# 定义变量存储布尔类型的数据
bool_1 = True
bool_2 = False
print(f"bool_1变量内容是{bool_1},类型是{type(bool_1)}")
print(f"bool_2变量内容是{bool_2},类型是{type(bool_2)}")
# 比较运算符的使用
num1 = 10
num2 = 10
num3 = 15
print(f"10 == 10 的结果是:{num1 == num2}")
print(f"10 != 15 的结果是:{num1 != num3}")
name1 = "it"
name2 = "its"
print(f"it == its 的结果是:{name1 == name2}")
print(f"10 >= 15 的结果是:{num1 >= num3}")
print(f"10 <= 15 的结果是:{num1 <= num3}")
print(f"10 >= 10 的结果是:{num1 >= num2}")
print(f"10 <= 10 的结果是:{num1 <= num2}")
if 语句的基本格式

if 要判断的条件:

条件成立时,要做的事情

# if语句的基本格式应用
age = 10
if age >= 18:
    print("已经成年了")
    print("步入大学")
print("时间过得真快")

PS:

  • 判断语句的结果必须是布尔类型 True或False;True会执行if内的代码语句;False则不会执行

  • 冒号:不要忘记

  • 归属于if判断的代码语句块,需在前方填充4个空格缩进,python通过缩进判断代码块的归属关系

**练习:**成年人判断

# 练习:成年人判断
# 1.通过input语句,获取键盘输入,为变量age赋值。(注意转换成数字类型)
# 2.通过if语句判断是否是成年人,满足条件则输出提示信息。
print("欢迎来到游乐场,儿童免费,成人收费。")
age = int(input("请输入您的年龄:"))
# age = int(age)
if age >= 18:
    print("您已成年,游玩需补票10元。")
print("祝您玩得愉快")
if else 语句

if 条件:

满足条件时要做的事情

······

else:

不满足条件时做的事情

······

# if else 的组合判断语句
age = int(input("请输入您的年龄:"))
if age >= 18:
    print("您已成年,需要补票。")
else:
    print("您未成年,可以免费游玩。")

PS:

  • else 后,不需要判断条件
  • 和if的代码块一样,else 的代码块同样需要4个空格作为缩进

**练习:**我要买票吗

# 练习:我要买票吗
"""
通过input语句获取键盘输入的身高
判断身高是否超过120cm,并通过print给出提示信息
"""
print("欢迎来到游乐园!")
high = int(input("请输入您的身高:"))
if high > 120:
    print("您的身高超过120cm,需要补票10元。")
else:
    print("您的身高未超出120cm,可免费游玩。")
print("祝您游玩愉快!")
if elif else 语句

if 条件1:

满足条件1应做的事情

elif 条件2:

满足条件2应做的事情

elif 条件N:

满足条件N应做的事情

else:

所有条件都不满足应做的事情

# if elif else 多条件判断语句的使用
height = int(input("请输入您的身高:"))
vip_level = int(input("请输入您的vip等级(1-5):"))
day = int(input("请告诉我今天几号:"))
if height < 120:
    print("身高小于120cm,可以免费。")
elif vip_level > 3:
    print("vip级别大于3,可以免费。")
elif day == 1:
    print("今天是1号免费日,可以免费。")
else:
    print("条件都不满足,需要买票10元。")

PS:

  • elif 语句可以写多个
  • 判断是互斥且有顺序的。满足1,将不会理会2和3;满足2,将不会理会3;1、2、3均不满足,进入else;else也可以省略不写,效果等同3个独立的if判断
  • 空格缩进同样不可省略
  • 可以将input输入语句直接写入判断条件中。目的是节省代码量。例:if int(input("输入身高:")) < 120:
  • 注释的快捷键是 ctrl + /

**练习:**猜猜心里数字

# 练习:猜猜心里数字
"""
1.定义一个变量,数字类型,内容随意
2.基于input语句输入猜想的数字,通过if和多次elif的组合,判断猜想数字是否和心里数字一致
"""
num = 5
if int(input("请输入第一次猜想的数字:")) == num:
    print("恭喜第一次就猜中了!")
elif int(input("不对,再猜一次:")) == num:
    print("恭喜第二次猜中了!")
elif int(input("不对,再猜最后一次:")) == num:
    print("恭喜第三次猜中了!")
else:
    print(f"对不起,全部猜错,所求数字为:{num}")
判断语句的嵌套

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于这种需求,我们可以自由组合 if elif else ,完成特定需求的要求

基础语法格式:

if 条件1:

满足条件1做的事情1

满足条件1做的事情2

if 条件2:

满足条件2做的事情1

满足条件2做的事情2

第二个 if ,属于第一个if内,只有第一个 if 满足条件,才会执行第二个 if

嵌套的关键点,在于:空格缩进

通过空格缩进,来决定语句之间的:层次关系

# 判断语句的嵌套使用
if int(input("您的身高是:")) > 120:
    print("您的身高超出120cm,不可以免费。")
    print("但是,如果vip大于3,可以免费。")
    if int(input("您的vip等级是:")) > 3:
        print("您可免费游玩!")
    else:
        print("抱歉,您VIP不达标,请补票10元。")
else:
    print("欢迎小朋友免费游玩!")

PS:

  • 1.嵌套判断语句可以用于多条件、多层次的逻辑判断
  • 2.嵌套判断语句可以根据需求,自由组合 if elif else 来构建多层次判断
  • 嵌套判断语句,一定要注意空格缩进,python通过空格缩进来决定层次关系
实战案例

案例需求:定义一个数字(1~10,随机产生),通过3次判断来猜出来数字

案例要求:

1.数字随机产生,范围1~10

2.有3次机会猜中数字,通过3层嵌套判断实现

3.每次猜不中,会提示大了或小了

提示:通过以下代码可以定义一个变量num,变量内存储随机数字。

import random

num = random.randint(1,10)

# 自己写的
import random
num = random.randint(1,10)
num1 = int(input("请输入第一次猜的数字:"))
if num1 > num:
    num2 = int(input("所猜数字大了,请猜第二次:"))
    if num2 > num:
        num3 = int(input("所猜数字大了,请猜第三次:"))
        if num3 == num:
            print("您猜对了!")
        else:
            print(f"您都猜错了,答案是:{num}")
    elif num2 < num:
        num3 = int(input("所猜数字小了,请猜第三次:"))
        if num3 == num:
            print("您猜对了!")
        else:
            print(f"您都猜错了,答案是:{num}")
    else:
        print("您第二次猜对了!")
elif num1 < num:
    num2 = int(input("所猜数字小了,请猜第二次:"))
    if num2 > num:
        num3 = int(input("所猜数字大了,请猜第三次:"))
        if num3 == num:
            print("您猜对了!")
        else:
            print(f"您都猜错了,答案是:{num}")
    elif num2 < num:
        num3 = int(input("所猜数字小了,请猜第三次:"))
        if num3 == num:
            print("您猜对了!")
        else:
            print(f"您都猜错了,答案是:{num}")
    else:
        print("您第二次猜对了!")
else:
    print(f"恭喜你第一次就猜中了!{num}")
# 课程讲的
# 构建一个随机的数字变量
import random
num = random.randint(1,10)
guess_num = int(input("请输入第一次猜的数字:"))
# 通过if判断语句进行数字的猜测
if guess_num == num:
    print("恭喜你第一次猜中了!")
else:
    if guess_num > num:
        print("您猜的大了")
    else:
        print("您猜的小了")
    guess_num = int(input("第二次输入您的猜测:"))
    if guess_num == num:
        print("恭喜你第二次猜中了!")
    else:
        if guess_num > num:
            print("您猜的大了")
        else:
            print("您猜的小了")
        guess_num = int(input("第三次输入您的猜测:"))
        if guess_num == num:
            print("恭喜你第三次猜中了!")
        else:
            print("三次机会用完了均未猜中。")

第四章 循环语句

**前言:**循环普遍存在于日常生活中,同样,在程序中,循环功能也是至关重要的基础功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

while循环的基础语法

while 条件:

条件满足时,做的事情1

条件满足时,做的事情2

条件满足时,做的事情3

······

# while循环的基础应用
i = 0
while i<5:
    print("o")
    i+=1

PS:

  • 1.while的条件需得到布尔类型,True表示继续循环,False表示结束循环
  • 2.需要设置循环终止的条件,如 i+=1 配合 i<100,就能确保100次后停止,否则将无限循环
  • 3.空格缩进和 if 判断一样,都需要设置

**练习案例:**求1-100的和

# 练习:求1-100的和
# 需求:通过while循环,计算从1累加到100的和
# 提示:
# 1.终止条件不要忘记,设置为确保while循环100次
# 2.确保累加的数字,从1开始,到100结束
i = 1
sum = 0
while i <= 100:
    sum += i
    i += 1
print(f"1-100累加的和是:{sum}")

while循环的基础案例

# 猜数字案例
# 设置一个范围1-100的随机变量,通过while循环,配合input语句,判断输入的数字是否等于随机数
# 1.无限次机会,直到猜中为止
# 2.每一次猜不中,会提示大了或小了
# 3.猜完数字后,提示猜了几次
# 提示:
# 1.无限次机会,终止条件不适合用数字累加来判断
# 2.可以考虑布尔类型本身(True或False)
# 3.需要提示几次猜中,就需要提供数字累加功能
# 4.随机数使用:    import random
#                 num = random.randint(1,100)

# 自写答案
import  random
num = random.randint(1,100)
number = 1
guess_num = int(input(f"请输入您第{number}次猜测的数字:"))
while guess_num != num:
    number += 1
    if guess_num > num:
        guess_num = int(input(f"您的猜测过大,请输入第{number}次猜测的数字:"))
    else:
        guess_num = int(input(f"您的猜测过小,请输入第{number}次猜测的数字:"))
print(f"您猜对了,共猜了{number}次。")
# 参考答案
# 获取范围在1-100的随机数字
import  random
num = random.randint(1,100)
# 通过一个布尔类型的变量,做循环是否继续的标记
flag = True
number = 0
while flag:
    guess_num = int(input("请输入您猜测的数字:"))
    number += 1
    if guess_num == num:
        print(f"您猜对了,共猜了{number}次。")
        # 设置为False就是终止循环的条件
        flag = False
    else:
        if  guess_num > num:
            print("您的猜测过大")
        else:
            print(f"您的猜测过小")
print(f"您猜对了,共猜了{number}次。")

while循环的嵌套应用

while 条件1:

条件1满足时,做的事情1

条件1满足时,做的事情2

条件1满足时,做的事情3

······

while 条件2:

条件2满足时,做的事情1

条件2满足时,做的事情2

条件2满足时,做的事情3

······

# while循环的嵌套使用
# 外层:表白100天的控制
# 内层:每天的表白都送10支花的控制
i = 1
while i <= 100:
    print(f"今天是第{i}天,准备表白")
    # 内层循环的控制变量
    j = 1
    while j <= 10:
        print(f"送给第{j}支花")
        j += 1
    i += 1
    print("我喜欢你")
print(f"坚持到第{i-1}天,表白成功")

PS:

  • 同判断语句的嵌套一样,循环语句的嵌套,要注意空格缩进
  • 基于空格缩进来决定层次关系
  • 注意条件的设置,避免出现无限循环(除非真的需要无限循环)

while循环的嵌套案例

补充知识-print输出不换行

  • 默认的print语句输出内容会自动换行
  • 在print语句中加上 end='' 即可输出不换行了,例如:print("hello",end='')
# 默认输出换行
print("Hello")
print("Hello")
# 使用end=",输出不换行
print("Hello",end='')
print("Hello",end='')

补充知识-制表符 \t

在字符串中,有一个特殊符号:\t,效果等同于在键盘上按下:tap键。它可以让我们的多行字符串进行对其。

# 制表符\t
print("Hello\tWorld")
print("Come\tOn")

**练习案例:**打印九九乘法表

# 练习:打印九九乘法表
# 通过while循环,输出如下九九乘法表内容
# 定义外层循环的控制变量
i = 1
while i <= 9:
    # 定义内层循环的控制变量
    j = 1
    while j <= i:
        # 内层循环的print语句,不要换行,通过\t制表符进行对齐
        print(f"{j}*{i}={i*j}\t",end='')
        j += 1
    # print()空内容,就是给出一个换行
    print()
    i += 1

for循环的基础语法

基础语法

for循环

除了while循环语句外,python同样提供了for循环语句。

两者能完成的基本功能差不多,但是仍有一些区别:

  • while循环的循环条件是自定义的,自行控制循环条件
  • for循环是一种 ”轮询“ 机制,是对一批内容进行 ”逐个处理“。(将”待办事项“逐个完成的循环机制)

语法:

for 临时变量 in 待处理数据集:

循环满足条件时执行的代码

# for循环的基础语法
name = "hello world"
for x in name:
    # 将name中的内容,挨个取出赋给x临时变量
    # 就可以在循环体内对x进行处理
    print(x)

PS:

  • 可以看出,for循环是将字符串的内容依次取出。所以,for循环也被称为:遍历循环

  • 同while循环不同,for循环是无法定义循环条件的,只能被动取出数据进行处理。

  • 只能从被处理的数据集中,依次取出内容进行处理。

  • 理论上讲,python中的for循环无法构建无限循环(被处理的数据集不可能无限大)

**练习:**数一数有几个a

# 练习:数一数有几个a
# 定义字符串变量name,内容为:”hello world,i love the world.“
# 通过for循环,遍历此字符串,统计有多少个英文字母:”l“
# 提示:
# 1.计数可以在循环外定义一个整数类型变量用来做累加计数
# 2.判断是否为字母”l“,可以通过if语句结合比较运算符来完成
name = "hello world,i love the world."
i = 0
for x in name:
    if x == "l":
        i += 1
print(f"被统计字符串中有{i}个l")
range语句

for 临时变量 in 待处理数据集:

循环满足条件时执行的代码

语法中的:待处理数据集,严格来说称之为:序列类型

**序列类型指:**其内容可以一个个依次取出的一种类型,包括:字符串、列表、元组等

for循环语句,本质上是遍历:序列类型

尽管除字符串外,其它的序列类型目前没有学习到,但是不妨碍我们通过学习range语句,获得一个简单的数字序列

语法1:

range(num)

获取一个从0开始,到num结束的数字序列(不包含num本身)。例:range(5)取得的数据是:[0,1,2,3,4]

语法2:

range(num1,num2)

获得一个从num1开始,到num2结束的数字序列(不包含num2本身)。例:range(5,10)得数据:[5,6,7,8,9]

语法3:

range(num1,num2,step)

获得一个从num1开始,到num2结束的数字序列(不包含num2本身)。数字之间的步长,以step为准(step默认为1)。

例:range(5,10,2)取得的数据是:[5,7,9]

# range语句的基本使用
# 语法1
for x in range(5):
    print(x)
# 语法2
for x in range(5,10):
    # 从5开始到10结束,不包含10本身的一个数字序列
    print(x)
# 语法3
for x in range(5,10,2):
    # 从5开始到10结束,不包含10本身的一个数字序列,数字间隔是2
    print(x)
# 用途:可以便捷使用循环次数
for x in range(10):
    print("hello world")

**PS:**range的用途有很多,多数用在for循环场景

**练习案例:**有几个偶数

# 练习:有几个偶数
# 定义一个数字变量num,内容随意
# 并使用range()语句,获取从1到num的序列,使用for循环遍历它
# 在遍历过程中,统计有多少偶数出现
# 提示:
# 1.序列可以使用:range(1,num)得到
# 2.偶数通过if来判断,判断数字余2是否为0即可
num = int(input("请输入一个数:"))
i =0
for x in range(1,num):
    if x%2 == 0:
        i += 1
print(f"从1到{num}一共有{i}个偶数")
变量作用域

for循环的变量作用域

for 临时变量 in 待处理数据集:

循环满足条件时执行的代码

临时变量,在编程规范上,作用范围(作用域),只限定在for循环内部

如果在for循环外部访问临时变量:

  • 实际上是可以访问到的
  • 在编程规范上,是不允许、不建议这么做的
# for循环临时变量的作用域
i = 0 # for循环外部访问临时变量,在for循环之前先定义好 
for i in range(5):
    print(i)
print(i)# 报黄色说明有问题。红色是警告。

PS:

  • 1.for循环中的临时变量,作用域限定为:循环内
  • 2.这种限定:是编程规范的限定,而非强制限定;不遵守也能正常运行,但不建议;如需访问临时变量,可以预先循环外定义它

for循环的嵌套应用

for 临时变量 in 待处理数据集(序列):

循环满足条件应做的事情1

循环满足条件应做的事情2

循环满足条件应做的事情N

······

for 临时变量 in 待处理数据集(序列):

循环满足条件应做的事情1

循环满足条件应做的事情2

循环满足条件应做的事情N

# 嵌套应用for循环
# 坚持表白100天
# range语句控制循环次数
x = 0
for x in range(100):
    print(f"第{x+1}天,加油坚持")
    # 写内层循环
    for i in range(10):
        print(f"第{i+1}朵玫瑰")
    print("我喜欢你")
print(f"第{x+1}天,表白成功")

**PS:**for循环和while循环可以相互嵌套使用

**练习案例:**for循环打印九九乘法表

# 练习:for循环打印九九乘法表
# 通过for循环,输出乘法表
# 通过外层循环控制行数
for i in range(1,10):
    # 通过内层循环控制每一行的数据
    for j in range(1,i+1):
        # 在内层循环中输出每一行的内容
        print(f"{j}*{i}={i*j}\t",end='')
    # 外层循环可以通过print输出一个回车符
    print()

循环中断:break和continue

python 中提供breakcontinue关键字用以对循环进行临时跳过和直接结束

continue

continue关键字用于**:**中断本次循环,直接进入下一次循环

continue可以用于:for循环和while循环,效果一致

for i in range(1,10):
	语句1
    continue
    语句2

上述代码:

  • 在循环内,遇到continue就结束当次循环,进行下一次
  • 所以,语句2是不会执行的

应用场景:在循环中,因某些原因,临时结束本次循环

continue在嵌套循环中的应用

continue关键字只可以控制:他所在的循环临时中断

for i in range(1,100):
	语句1
    for j in range(1,100):
        语句2
        continue
        语句3 # 每次内层循环只会跳过语句3,其他代码正常运行,不影响外层循环
    语句4

break

break关键字用于:直接结束循环

break可以用于:for循环和while循环,效果一致

for i in range(1,100):
    语句1
    break
    语句2
语句3

上述代码:

  • 在循环内,遇到break就结束循环了
  • 所以,执行了语句1后,直接执行语句3

break在嵌套循环中的应用

break关键字同样只可以控制:它所在的循环结束

for i in range(1,100):
	语句1
    for j in range(1,100):
        语句2
        break # 导致内层循环整个直接结束,语句2只输出一次,后内存循环结束,外层循环不受影响
        语句3 
    语句4

示例:

# 循环语句的中断控制:continue和break
# 循环中断语句continue
for i in range(1,6):
    print("语句1")
    continue
    # 语句2不会被执行
    print("语句2")
# continue的嵌套应用
for i in range(1,6):
    print("语句1")
    for j in range(1, 6):
        print("语句2")
        continue
        # 语句3不会被执行
        print("语句3")
    print("语句4")
print()
# 循环中断语句break
for i in range(1,101):
    print("语句1")
    break
    # 语句2不会被执行
    print("语句2")
print("语句3")
# break的嵌套应用
for i in range(1,6):
    print("语句1")
    for j in range(1, 6):
        print("语句2")
        break
        # 语句3不会被执行
        print("语句3")
    print("语句4")

PS:

  • continue的作用是:中断所在循环的当次执行,直接进入下一次
  • break的作用是:直接结束所在的循环
  • continue和break,在for和while循环中作用一致
  • 在嵌套循环中,只能作用在所在的循环上,无法对上层循环起作用

综合案例

**练习案例:**发工资

# 练习:发工资
# 某公司,账户余额有1万元,给20名员工发工资
# 员工编号从1到20,从编号1开始,依次领工资,每人1000元
# 领工资时,财务判断员工的绩效分(1-10)(随机生成),如果低于5,不发工资,换下一位
# 如果工资发完了,结束发工资
# 提示:
# 1、使用循环对员工依次发工资
# 2、continue用于跳过员工,break用于直接结束发工资
# 3、随机数可以用:
#       import random
#       num = random.randint(1,10)

# 自己写的
money = 10000
for i in range(1,21):
    if money > 0:
        import random
        num = random.randint(1, 10)
        if num >= 5:
            money -= 1000
            print(f"向员工{i}发工资1000元,账户余额:{money}。")
        else:
            print(f"员工{i},绩效分{num},低于5,不发工资,下一位。")
    else:
        print("工资发完了,下个月领取吧。")
        break
# 参考答案
# 定义账户余额变量
money = 10000
# for循环对员工发放工资
for i in range(1,21):
    import random
    num = random.randint(1, 10)
    if num < 5:
        print(f"员工{i},绩效分{num},低于5,不发工资,下一位。")
        # continue跳过绩效不达标的员工
        continue
    # 要判断余额是否充足
    if money > 0:
        money -= 1000
        print(f"向员工{i}发工资1000元,账户余额:{money}。")
    else:
        print("工资发完了,下个月领取吧。")
        # break结束发放
        break

第五章 函数

函数介绍

**函数:**是组织好的,可重复使用的,用来实现特定功能的代码段

# 统计字符串的长度,不使用内置函数len()
str1 = "itheima"
str2 = "itcast"
str3 = "python"
# 定义一个计数的变量
count = 0
for i in str1:
    count += 1
print(f"字符串{str1}的长度是:{count}")
count = 0
for i in str2:
    count += 1
print(f"字符串{str2}的长度是:{count}")
count = 0
for i in str3:
    count += 1
print(f"字符串{str3}的长度是:{count}")
# 可以使用函数来优化这个过程
def my_len(data):
    count = 0
    for i in data:
        count += 1
    print(f"字符串{data}的长度是:{count}")
my_len(str1)
my_len(str2)
my_len(str3)

**学习使用函数的原因是:**为了得到一个针对特定需求、可供重复利用的代码段,提高程序的复用性,减少重复代码,提高开发效率

使用函数的好处是:

  • 将功能封装在函数内,可供随时地重复利用
  • 提高代码的复用性,减少重复代码,提高开发效率

函数的定义

def 函数名(传入参数):

函数体

return 返回值

函数的调用:函数名(参数)

# 定义一个函数,输出相关信息
def say_hi():
    print("hello world")
# 调用函数,让定义的函数开始工作
say_hi()

注意:

  • 参数如不需要,可以省略
  • 返回值如不需要,可以省略
  • 函数必须先定义,后调用

**练习案例:**自动查核酸

# 练习:自动查核酸
# 定义一个函数,函数名任意,要求调用函数后可以输出指定语句
# 定义函数
def say_word():
    # 编写函数体输出信息
    print("欢迎光临!")
    print("请出示24小时核算证明!")
# 调用函数 
say_word()

函数的参数

函数的传入参数:传入参数的数量是不受限制的

  • 可以不使用参数
  • 也可以使用任意N个参数

**传入参数的功能是:**在函数进行计算的时候,接受外部(调用时)提供的数据

基于函数的定义语法:

def 函数名(传入参数):

函数体

return 返回值

# 函数使用参数
# 定义两数相加的函数,通过参数接收被计算的两个数字
def add(x,y):
    result = x + y
    print(f"{x}+{y}={result}")
# 调用函数,传入被计算的两个数字
add(3,5)
  • 函数定义中,提供的x和y,称之为:形式参数(形参),表示函数声明将要使用2个参数
  • 参数之间使用逗号分隔
  • 函数调用中,提供的5和6,称之为:实际参数(实参),表示函数执行时真正使用的参数值
  • 传入的时候,按照顺序传入数据,使用逗号分隔

**练习案例:**升级版自动查核酸

# 练习
# 定义一个函数,名称任意,并接受一个参数传入(数字类型,表示体温)
# 在函数内进行提问判断(正常范围:小于等于37.5),并输出指定内容
# 定义函数,接收1个形参,数字类型,表示体温
def check_temp(x):
    # 在函数体内进行体温判断
    if x <= 37.5:
        print(f"欢迎光临,您的体温为{x}度,体温正常请进!")
    else:
        print(f"欢迎光临,您的体温为{x}度,体温异常,需要隔离!")
# 调用函数,传入实参
check_temp(37.3)
check_temp(38)

函数的返回值

函数返回值的定义

**返回值:**就是程序中函数完成事情后,最后给调用者的结果

def 函数名(传入参数):

函数体

return 返回值

变量 = 函数(参数)

# 定义函数返回值的语法格式
# 定义一个函数,完成2数相加的功能
def add(x,y):
    result = x + y
    # 通过返回值,将相加的结果返回给调用者
    return result
    # 返回结果后,还想输出一句话
    print("我完事了") # 遇到return后,后面的代码将不会执行
# 函数的返回值,可以通过变量去接受
r = add(5,6)
print(r)

**注意:**函数体遇到return后就结束了,所以写在return后的代码不会执行

None类型

思考:如果函数没有使用return语句返回数据,那么函数有返回值吗?

实际上是:有的。

python中有一个特殊的字面量:None,其类型是:<class 'NoneType>

无返回值的函数,实际上就是返回了:None这个字面量

**None表示:**空的、无实际意义的意思

函数返回的None,就表示这个函数没有返回什么有意义的内容,也就是返回了空的意思。

None类型的应用场景

None作为一个特殊的字面量,用于表示:空、无意义,其有非常多的应用场景。

  • 用在函数无返回值上

  • 用在if判断上

    • 在if判断中,None等同于False
    • 一般用于在函数中主动返回None,配合if判断做相关处理
  • 用于声明无内容的变量上

    • 定义变量,但暂时不需要变量有具体值,可以用None来代替
    • name = None # 暂不赋予变量具体值
# None
# 无return语句的函数返回值
def say_hi():
    print("你好")
result = say_hi()
print(f"无返回值函数,返回的内容是:{result},类型是:{type(result)}")

# 主动返回None的函数
def say_hi2():
    print("你好呀")
    return None
result = say_hi2()
print(f"无返回值函数,返回的内容是:{result},类型是:{type(result)}")

# None用于if判断
def check_age(age):
    if age > 18:
        return "SUCCESS"
    else:
        return None
result = check_age(16)
if not result:
    # 进入if表示result是None值,也就是false
    print("未成年,不可以进入")
    
# None用于声明无初始内容的变量
name = None

函数说明文档

函数是纯代码语言,想要理解其含义,就需要一行行的去阅读理解代码,效率较低。

我们可以给函数添加说明文档,辅助理解函数的作用。

通过多行注释的形式,对函数进行说明解释。(内容应写在函数体之前)

# 对函数进行文档说明
# 定义函数,进行文档说明
def add(x,y):
    """
    add函数可以接收2个参数,进行两个参数相加的功能
    :param x: 形参x表示相加的其中一个数字
    :param y: 形参y表示相加的另一个数字
    :return: 返回值是两数相加的结果
    """
    result = x + y
    print(f"{x}+{y}={result}")
    return result
add(5,6)

**PS:**在PyCharm编写代码时,可以通过鼠标悬停在传参位置,查看调用函数的说明文档

函数的嵌套调用

函数的嵌套调用指的是:一个函数里面又调用了另外一个函数

# 嵌套调用函数
# 定义func_b
def func_b():
    print("--2--")
# 定义func_a,并在内部调用func_b
def func_a():
    print("--1--")
    # 嵌套调用func_b
    func_b()
    print("--3--")
# 调用函数func_a
func_a()

如果在函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次函数A执行的位置,继续执行A剩下内容

变量的作用域

局部变量

变量作用域指的是变量的作用范围(变量在哪里可用,在哪里不可用)

主要分为两类:局部变量和全局变量

所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效

**局部变量的作用:**在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量

全局变量

所谓全局变量,指的是在函数体内、外都能生效的变量

若有一个数据,在函数A和函数B中都要使用,那应该把这个数据存储在一个全局变量里面

global关键字

使用 global 关键字可以在函数内部声明变量为全局变量

语法:global 变量名

# 变量作用域
# 局部变量
def test_ja():
    num = 100
    print(num)
test_ja()
# 出了函数体,局部变量就无法使用了
# print(num)

# 全局变量
num = 200
def test_qa():
    print(f"test_qa:{num}")
def test_qb():
    print(f"test_qb:{num}")
test_qa()
test_qb()
print(num)

# 在函数内修改全局变量
num = 200
def test_xqa():
    print(f"test_xqa:{num}")
def test_xqb():
    num = 500 # 局部变量
    print(f"test_xqb:{num}")
test_xqa()
test_xqb()
print(num)

# global关键字,在函数内声明变量为全局变量
num = 200
def test_gxqa():
    print(f"test_gxqa:{num}")
def test_gxqb():
    global num      # 设置内部定义的变量为全局变量
    num = 500
    print(f"test_gxqb:{num}")
test_gxqa()
test_gxqb()
print(num)

综合案例

# 综合案例:ATM
# 定义一个全局变量:money,用来记录银行卡月(默认5000000)
# 定义一个全局变量:name,用来记录客户姓名(启动程序时输入)
# 定义如下的函数:
#     查询余额函数
#     存款函数
#     取款函数
#     主菜单函数
# 要求:
#     程序启动后要求输入客户姓名
#     查询余额、存款、取款后都会返回主菜单
#     存款、取款后,都应显示一下当前余额
#     客户选择退出或输入错误,程序会推出,否则一直运行
# 定义全局变量name和money
money = 5000000
name = None
# 要求客户输入姓名
name = input("请输入您的姓名:")
# 定义查询函数
def query(show_header):
    # 通过参数控制内容的输出
    if show_header:
        print("--------------查询余额--------------")
    print(f"{name},您好,您的余额剩余:{money}元")
# 定义存款函数
def in_money(num):
    global money # money在函数内部定义为全局变量
    money += num
    print("--------------存款--------------")
    print(f"{name},您好,您存款{num}元成功")
    # 调用query()函数查询余额
    query(False)
# 定义取款函数
def out_money(num):
    global money
    money -= num
    print("--------------取款--------------")
    print(f"{name},您好,您取款{x}元成功")
    # 调用query()函数查询余额
    query(False)
# 定义主菜单函数
def show_tap():
    print("---------------主菜单---------------")
    print(f"{name},您好,欢迎来到ATM,请选择操作:")
    print("查询余额\t[输入1]")
    print("存款\t\t[输入2]")
    print("取款\t\t[输入3]")
    print("退出\t\t[输入4]") # 通过\t制表符对齐输出
    return input("请选择操作:")
# 设置无限循环,确保程序不退出
while True:
    x = show_tap()
    if x == "1":
        query(True)
        continue # 通过continue继续下一次循环,一进来就回到了主菜单
    elif x == "2":
        num = int(input("您想要存多少钱?请输入:"))
        in_money(num)
        continue
    elif x == "3":
        num = int(input("您想要取多少钱?请输入:"))
        out_money(num)
        continue
    else:
        print("程序退出。")
        # 通过break退出循环
        break

第六章 数据容器

数据容器入门

优雅、高效

学习数据容器,就是为了批量存储或批量使用多份数据

**python中的数据容器:**一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素;每一个元素,可以是任意类型的数据,如字符串、数字、布尔等。

数据容器根据特点的不同,如:

  • 是否支持重复元素
  • 是否可以修改
  • 是否有序等

分为5类,分别是:列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)

数据容器:list(列表)

列表的定义

基本语法:

# 字面量
[元素1,元素2,元素3,元素4,...]

# 定义变量
变量名称 = [元素1,元素2,元素3,元素4,...]

# 定义空列表
变量名称 = []
变量名称 = list()

列表(数据容器)内的每一个数据,都称之为元素

  • [] 作为标识
  • 列表内每一个元素之间用 逗号隔开
# list列表
# 定义一个列表 list
my_list = ["hello","world","python"]
print(my_list)
print(type(my_list))
my_list = ["hello",666,True]
print(my_list)
print(type(my_list))

# 定义一个嵌套的列表
my_list = [[1,2,3],[4,5,6]]
print(my_list)
print(type(my_list))

**注意:**列表可以一次存储多个数据,且可以为不同的数据类型,元素也可以是列表,所以支持嵌套

列表的下标索引

列表中的每一个元素,都有其位置编号,称之为下标索引,从前向后的方向,从0开始,依次递增

语法:列表[下标索引]

**列表的下标(索引)—反向:**从后向前:从-1开始,依次递减(-1、-2、-3…)

嵌套列表的下标(索引):语法列表[下标][下标]

# 通过下标索引取出对应位置的数据
my_list = ["tom","lily","lee"]
# 列表[下标索引],从前向后从0开始,每次+1;从后向前从-1开始,每次-1
print(my_list[0])
print(my_list[1])
print(my_list[2])
# 错误示范:通过下标索引取数据,一定不要超出范围
# print(my_list[2])

# 通过下标索引取出数据(倒序取出)
print(my_list[-1])
print(my_list[-2])
print(my_list[-3])

# 取出嵌套列表的元素
my_list = [[1,2,3],[4,5,6]]
print(my_list[1][1])

注意:

  • 要注意下标索引的取值范围,超出范围无法取出元素,并且会报错
列表的常用操作
  • 定义
  • 使用下标索引获取值
  • 插入元素
  • 删除元素
  • 清空元素
  • 修改元素
  • 统计元素个数

等等功能,这些功能称之为:列表的方法

回忆:

  • 函数是一个封装的代码单元,可以提供特定功能

  • 在python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法

  • 方法和函数功能一样,有传入参数,有返回值,只是方法的使用格式不同:

    • 函数的使用:num = add(1,2)
    • 方法的使用:student = Student()
    • num = student.add(1,2)

列表的查询功能(方法)

  • 查找某元素的下标
    • 功能:查找指定元素在列表的下标,如果找不到,报错ValueError
    • 语法:列表.index(元素)
    • index就是列表对象(变量)内置的方法(函数)

列表的修改功能(方法)

  • 修改特定位置(索引)的元素值:

    • 语法:列表[下标]=值
    • 可以使用如上语法,直接对指定下标(正向、反向下标均可)的值进行:重新赋值(修改)
  • 插入元素:

    • 语法:列表.insert(下标,元素),在指定的下标位置,插入指定的元素
  • 追加元素(单个元素):

    • 语法:列表.append(元素),将指定元素,追加到列表的尾部
  • 追加元素(一批元素)

    • 语法:列表.extend(其他数据容器),将其它数据容器的内容取出,依次追加到列表尾部
  • 删除元素:

    • 语法1:del列表[下标]
    • 语法2:列表.pop(下标)
  • 删除某元素在列表中的第一个匹配项

    • 语法:列表.remove(元素)
  • 清空列表内容:

    • 语法:列表.clear()
  • 统计某元素在列表内的数量

    • 语法:列表.count(元素)
  • 统计列表内,有多少元素

    • 语法:len(列表)
    • 可以得到一个int数字,表示列表内的元素数量
# list列表的常用操作
my_list = ["hello","world","python"]
# 1.1查找元素在列表内的下标索引
index = my_list.index("world")
print(f"world在列表中的下标索引值为:{index}")
# 1.2如果被查找的元素不存在,会报错
# index = my_list.index("why")
# print(f"why在列表中的下标索引值为:{index}")

# 2.修改特定下标索引的值
my_list[0] = "xatu"
print(f"列表修改元素之后的结果是:{my_list}")

# 3.在指定下标位置插入新元素
my_list.insert(1,"hello")
print(f"列表插入元素之后的结果是:{my_list}")

# 4.在列表尾部追加 单个 新元素
my_list.append("best")
print(f"列表追加单个元素之后的结果是:{my_list}")

# 5.在列表尾部追加 一批 新元素
my_list2 = [1,2,3]
my_list.extend(my_list2)
print(f"列表追加一批元素之后的结果是:{my_list}")

# 6.删除指定下标索引的元素
my_list = ["hello","world","python"]
# 6.1 方式1:del 列表[下标]
del my_list[2]
print(f"列表删除元素之后的结果是:{my_list}")
# 6.2 方式2:列表 pop(下标)
my_list = ["hello","world","python"]
element = my_list.pop(2)
print(f"列表通过pop删除元素之后的结果是:{my_list},取出的元素是:{element}")

# 7.删除某元素在列表中的第一个匹配项
my_list = ["hello","world","hello","world","python"]
my_list.remove("world")
print(f"通过remove方法移除元素之后的结果是:{my_list}")

# 8.清空列表
my_list.clear()
print(f"列表清空了,结果是:{my_list}")

# 9.统计列表内某元素的数量
my_list = ["hello","world","hello","world","python"]
count = my_list.count("hello")
print(f"列表中hello的数量是:{count}")

# 10.统计列表中全部的元素数量
count = len(my_list)
print(f"列表中的元素个数是:{count}个")

列表的方法——总览

编号使用方式作用
1列表.append(元素)向列表中追加一个元素
2列表.extend(容器)将数据容器的内容依次取出,追加到列表尾部
3列表.insert(下标,元素)在指定下标处,插入指定的元素
4del 列表[下标]删除列表指定下标元素
5列表.pop(下标)删除列表指定下标元素
6列表.remove(元素)从前向后,删除此元素的第一个匹配项
7列表.clear()清空列表
8列表.count(元素)统计此元素在列表中的出现次数
9列表.index(元素)查找指定元素在列表的下标,找不到报错ValueError
10len(列表)统计容器内有多少元素

列表的特点:

  • 可以容纳多个元素(上限为2**63-1、9223372036854775807个)
  • 可以容纳不同类型的元素(混装)
  • 数据是有序存储的(有下标序号)
  • 允许重复数据存在
  • 可以修改(增加或删除元素等)

**练习案例:**常用功能练习

# 练习
# 有一个列表,内容是:[21,25,21,23,22,20],记录的是一批学生的年龄
# 通过列表的功能(方法),对其进行
# 1.定义这个列表,并用变量接收它
age = [21,25,21,23,22,20]
# 2.追加一个数字31,到列表尾部
age.append(31)
# 3.追加一个新列表[29,33,30],到列表尾部
# 参考答案是:age.extend([29,33,30])
addage = [29,33,30]
age.extend(addage)
# 4.取出第一个元素(应是:21)
num1 = age[0]
print(f"从列表中取出来的第一个元素,应该是21,实际是:{num1}")
# 5.取出最后一个元素(应是:30)
num2 = age[-1]
print(f"从列表中取出来的最后一个元素,应该是30,实际是:{num2}")
# 6.查找元素31,在列表中的下标位置
index = age.index(31)
print(f"元素31在列表中的下标位置是:{index}")
print(f"列表的内容是:{age}")

list(列表)的遍历

列表的遍历——while循环

将容器内的元素依次取出进行处理的行为,称之为:遍历、迭代。

  • 可以使用前面学过的while循环遍历列表元素
  • 使用列表[下标]的方式取出列表元素
  • 控制循环条件:定义一个变量表示下标,从0开始
  • 循环条件为 下标值<列表的元素数量

列表的遍历——for循环

出了while循环外,另一种循环形式:for循环

对比while,for循环更加适合对列表等数据容器进行遍历

语法:for 临时变量 in 数据容器

对临时变量进行处理

表示从容器内,依次取出元素并赋值到临时变量上;在每一次的循环中,我们可以对临时变量(元素)进行处理

# list列表的循环
def list_while_func():
    # 使用while循环遍历列表
    my_list = ["hello","world","python"]
    # 循环控制变量通过下标索引来控制,默认为0
    # 每一次循环将下标索引变量+1
    # 循环条件:下标索引变量<列表的元素数量
    # 定义一个变量用来标记列表的下标
    index = 0   # 初始值为0
    while index < len(my_list):
        # 通过index变量取出对应下标的元素
        element = my_list[index]
        print(f"列表的元素:{element}")
        # 将循环变量index每一次循环都+1
        index += 1
def list_for_func():
    # 使用for循环遍历列表
    my_list = [1,2,3,4,5]
    # for 临时变量 in 数据容器:
    for element in my_list:
        print(f"列表的元素:{element}")
list_while_func()
list_for_func()

while循环和for循环的对比(都是循环语句,但是细节不同)

  • 在循环控制上:
    • while循环可以自定循环条件,并自行控制
    • for循环不可以自定循环条件,只可以一个个从容器内取出数据
  • 在无限循环上:
    • while循环可以通过条件控制做到无限循环
    • for循环理论上不可以,因为被遍历的容器容量不是无限的
  • 在使用场景上:
    • while循环适用于任何想要循环的场景
    • for循环适用于遍历数据容器的场景或简单的固定次数循环的场景
  • 综上所述:for循环更简单,while更灵活

**练习案例:**取出列表内的偶数

# 练习
# 定义一个列表,内容是:[1,2,3,4,5,6,7,8,9,10]
# 遍历列表,取出列表内的偶数,并存入一个新的列表对象中
# 使用while循环和for循环各操作一次
# 提示:
# 通过if判断来确认偶数
# 通过列表的append方法,来增加元素
my_list = [1,2,3,4,5,6,7,8,9,10]
new_list = list()
index = 0
while index < len(my_list):
    if my_list[index]%2 == 0:
        new_list.append(my_list[index])
    index += 1
print(f"通过while循环,从列表{my_list}中取出偶数,组成新列表:{new_list}")
my_list = [1,2,3,4,5,6,7,8,9,10]
new_list = []
for x in my_list:
    if x % 2 == 0:
        new_list.append(x)
print(f"通过for循环,从列表{my_list}中取出偶数,组成新列表:{new_list}")

数据容器:tuple(元组)

元组同列表一样,都是可以封装多个、不同类型的元素在内。

但最大的不同点在于:元组一旦定义完成、就不可修改。所以需要在程序内封装数据,又不希望封装的数据被篡改,就需要用到元组

**元组的定义:**定义元组使用小括号,且使用逗号隔开各个数据,数据可以是不同的数据类型

# 定义元组字面量
(元素,元素,......,元素)
# 定义元组变量
变量名称 = (元素,元素,......,元素)
# 定义空元组
变量名称 = ()			# 方式1
变量名称 = tuple()		# 方式2

注意:元组只有一个数据,这个数据后面要添加逗号

元组的相关操作:

编号方法作用
1index()查找某个数据,如果存在则返回对应下标,否则报错
2count()统计某个数据在当前元组出现的次数
3len(元组)统计元组内的元素个数
# tuple元组的定义和操作
# 定义元组
t1 = (1,"hello",True)
t2 = ()
t3 = tuple()
print(f"t1的类型是:{type(t1)},内容是:{t1}")
print(f"t2的类型是:{type(t2)},内容是:{t2}")
print(f"t3的类型是:{type(t3)},内容是:{t3}")

# 定义单个元素的元组
t4 = ("hello",)
print(f"t4的类型是:{type(t4)},内容是:{t4}")

# 元组的嵌套
t5 = ((1,2,3),(4,5,6))
print(f"t5的类型是:{type(t5)},内容是:{t5}")

# 下标索引去取出内容
num = t5[1][2]
print(f"从嵌套元组中取出的数据是:{num}")

# 元组的操作:index查找法
t6 = ("hello","world","python")
index = t6.index("world")
print(f"在元组t6中查找world的下表是:{index}")

# 元组的操作:count统计方法
t7 = ("hello","world","world","world","python")
count = t7.count("world")
print(f"在元组t7中world的个数是:{count}")

# 元组的操作:len函数统计元组元素数量
t8 = ("hello","world","world","world","python")
num = len(t8)
print(f"元组t8中元素的个数是:{num}")

# 元组的遍历:while
index = 0
while index < len(t8):
    print(f"元组的元素有{t8[index]}")
    index += 1

# 元组的遍历:for
for element in t8:
    print(f"2元组的元素有{element}")

# 修改元组的内容
# t8[0] = "ok"

# 定义一个元组,修改里面list的内容
t9 = (1,2,["hello","world"])
print(f"t9的内容是:{t9}")
t9[2][0] = "ok"
t9[2][1] = "good"
print(f"t9的内容是:{t9}")

注意事项:

  • 不可以修改元组的内容,否则直接会报错
  • 可以修改元组内的 list 的内容(修改元素、增加、删除、反转等)

元组的特点:

  • 可以容纳多个数据
  • 可以容纳不同类型的数据(混装)
  • 数据是有序存储(下标索引)
  • 允许重复数据存在
  • 不可修改(增加或删除元素等)
  • 支持for循环和while循环

多数特性和 list 一致,不同点在于不可修改的特性

**练习案例:**元组的基本操作

# 练习
# 定义一个元组,内容是:('周杰伦',11,['football',music]),记录的是一个学生的信息(姓名、年龄、爱好)
# 请通过元组的功能(方法),对其进行
stu = ('周杰伦',11,['football','music'])
# 1.查询其年龄所在的下标位置
num = stu.index(11)
print(f"学生年龄下标位置:{num}")
# 2.查询学生的姓名
print(f"学生的姓名:{stu[0]}")
# 3.删除学生爱好中的football
del stu[2][0]
print(f"学生信息:{stu}")
# 4.增加爱好:coding到爱好list内
stu[2].append("coding")
print(f"学生信息:{stu}")

数据容器:str(字符串)

字符串是字符的容器,一个字符串可以存放任意数量的字符。如,字符串:"hello"

字符串的下标(索引)

和其它容器如:列表、元组一样,字符串也可以通过下标进行访问

  • 从前向后,下标从0开始
  • 从后向前,下标从-1开始

同元组一样,字符串是一个:无法修改的数据容器。

所以:修改指定下标的字符;移除特定下标的字符;追加字符等。均无法完成。

如果必须要做,我们只能得到一个新字符串,老的字符串无法修改好。

字符串的常用操作:

  • 查找特定字符串的下标索引值
    • 语法:字符串.index(字符串)
  • 字符串的替换
    • 语法:字符串.replace(字符串1,字符串2)
    • 功能:将字符串内的全部:字符串1,替换为字符串2
    • 注意:不是修改字符串本身,而是得到了一个新字符串
  • 字符串的分割
    • 语法:字符串.split(分隔符字符串)
    • 功能:按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中
    • 注意:字符串本身不变,而是得到了一个列表对象
  • 字符串的规整操作(去前后空格)
    • 语法:字符串.strip()
  • 字符串的规整操作(去前后指定字符串)
    • 语法:字符串.strip(字符串)
    • 注意:传入的是 “12” 其实就是:“1” 和 “2” 都会移除,是按照单个字符

字符串常用操作汇总

操作说明
字符串[下标]根据下标索引取出特定位置字符
字符串.index(字符串)查找给定字符的第一个匹配项的下标
字符串.replace(字符串1,字符串2)将字符串内的全部字符串1,替换为字符串2;不修改原字符串,而是得到一个新字符串
字符串.split(字符串)按照给定字符串,对字符串进行分割;不会修改原字符串,而是得到一个新的列表
字符串.strip() 字符串.strip(字符串)移除首尾的空格和换行符或指定字符串
字符串.count(字符串)统计字符串内某个字符串的出现次数
len(字符串)统计字符串的字符个数
# 字符串的相关操作
my_str = "hello world and good"
# 通过下标索引取值
value = my_str[0]
value2 = my_str[-1]
print(f"字符串第一个元素为:{value},最后一个元素值为:{value2}")
# 字符串只读,不能修改
# my_str[0] = "a"

# index方法
index = my_str.index("and")
print(f"在字符串{my_str}中查找and,其起始下标为:{index}")

# replace方法
new_my_str = my_str.replace("o","错")
print(f"将字符串{my_str},进行替换后得到:{new_my_str}")

# split方法
my_str = "hello world and good"
my_str_list = my_str.split(" ")
print(f"将字符串{my_str},进行split切分后得到:{my_str_list},类型是:{type(my_str_list)}")
# 运行结果可以看到,字符串按照给定的<空格>进行了分割,变成了多个子字符串,并存入一个列表对象中

# strip方法
my_str = "  hello world and good  "
new_my_str = my_str.strip() # 不传入参数,就是去除字符串首尾空格
print(f"将字符串{my_str},进行strip操作后得到:{new_my_str}")
my_str = "12hello world and good21"
new_my_str = my_str.strip("12")
print(f"将字符串{my_str},进行strip('12')操作后得到:{new_my_str}")

# 统计字符串中某字符串的出现次数
count = my_str.count("o")
print(f"在字符串{my_str}中o出现的次数是:{count}")

# 统计字符串的长度
len = len(my_str)
print(f"字符串{my_str}的长度是:{len}")

**字符串的遍历:**同列表、元组一样,字符串也支持while循环和for循环进行遍历

# 字符串的遍历
my_str = "世界你好"
# while循环
index = 0
while index < len(my_str):
    print(f"while循环的遍历:{my_str[index]}")
    index += 1
# for循环
for x in my_str:
    print(f"for循环的遍历:{x}")

字符串的特点:

  • 只可以存储字符串
  • 长度任意(取决于内存大小)
  • 支持下标索引
  • 允许重复字符串存在
  • 不可以修改(增加或删除元素)
  • 支持while和for循环遍历

**练习案例:**分割字符串

# 练习
# 给定一个字符串:"itheima itcast boxuegu"
my_str = "itheima itcast boxuegu"
# 统计字符串内有多少个"it"字符
count = my_str.count("it")
print(f"字符串{my_str}内有{count}个'it'字符")
# 将字符串内的空格,全部替换为字符:"|"
new_my_str = my_str.replace(" ","|")
print(f"将字符串{my_str}内的空格,全部替换后的结果是:{new_my_str}")
# 并按照"|"进行字符串分割,得到新表
new_new_my_str = new_my_str.split("|") # 此时创建的为一个新的列表
print(f"将字符串{new_my_str}按照|进行字符串分割,得到新表的结果是:{new_new_my_str}")

数据容器(序列)的切片

序列

序列是指:内容连续、有序,可以使用下标索引的一类数据容器

列表、元组、字符串,均可以视为序列。

序列的常用操作-切片

  • 序列支持切片,即:列表、元组、字符串,均支持进行切片操作。切片:从一个序列中,取出一个子序列
  • 语法:序列[起始下标:结束下标:步长]
  • 表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列
    • 起始下标表示从何处开始,可以留空,留空视作从头开始
    • 结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
    • 步长表示,依次取元素的间隔
      • 步长1表示,一个个取元素
      • 步长2表示,每次跳过1个元素取
      • 步长N表示,每次跳过N-1个元素取
      • 步长为负数表示,反向取(注意:起始下标和结束下标也要反向标记)(表示倒叙执行)

**注意:**此操作不会影响序列本身,而是会得到一个新的序列(列表、元组、字符串)

# 对序列进行切片操作

# 对list进行切片,从1开始,4结束,步长1
my_list = [0,1,2,3,4,5,6]
result1 = my_list[1:4]    # 步长默认为1,所以可以省略不写
print(f"结果1:{result1}")

# 对tuple进行切片,从头开始,到最后结束,步长1
my_tuple = (0,1,2,3,4,5,6)
result2 = my_tuple[:]   # 起始和结束不写表示从头到尾,步长为1可以省略
print(f"结果2:{result2}")

# 对str进行切片,从头开始,到最后结束,步长2
my_str = "01234567"
result3 = my_str[::2]
print(f"结果3:{result3}")

# 对str进行切片,从头开始,到最后结束,步长-1
my_str = "01234567"
result4 = my_str[::-1]  # 等同于将序列反转了
print(f"结果4:{result4}")

# 对列表进行切片,从3开始,到1结束,步长为-1
my_list = [0,1,2,3,4,5,6]
result5 = my_list[3:1:-1]    # 步长默认为1,所以可以省略不写
print(f"结果5:{result5}")

# 对元组进行切片,从头开始,到尾结束,步长为-2
my_tuple = (0,1,2,3,4,5,6)
result6 = my_tuple[::-2]   # 起始和结束不写表示从头到尾,步长为1可以省略
print(f"结果6:{result6}")

**练习案例:**序列的切片实践

# 练习
# 有字符串:"欢迎到来,啊好你界世,hello world"
# 使用学过的任何方式,得到“世界你好”
# 可用方式参考:
# 倒叙字符串,切片取出然后倒序
my_str = "欢迎到来,啊好你界世,hello world"
resurt1 = my_str[9:5:-1]
print(f"从{my_str}取出得到:{resurt1}")
# split分割“,”,replace替换“啊”为空,倒叙字符串
resurt2 = my_str.split(",")
print(f"{resurt2}")
resurt3 = resurt2[1].replace("啊","")
print(f"{resurt3}")
resurt4 = resurt3[::-1]
print(f"{resurt4}")

# 参考答案
# 倒叙字符串,切片取出
my_str = "欢迎到来,啊好你界世,hello world"
resurt1 = my_str[::-1][12:16]
print(f"从{my_str}取出得到:{resurt1}")
# 切片取出,然后倒叙
resurt2 = my_str[6:10][::-1]
print(f"从{my_str}取出得到:{resurt2}")
# split分割“,”,replace替换“啊”为空,倒叙字符串
resurt3 = my_str.split(",")[1].replace("啊","")[::-1]
print(f"从{my_str}取出得到:{resurt3}")

数据容器:set(集合)

集合的主要特点就是:不支持元素的重复(自带去重功能)、并且内容无序

基本语法:

# 定义集合字面量
{元素,元素,......,元素}
# 定义集合变量
变量名称 = {元素,元素,......,元素}
# 定义空集合
变量名称 = set()

和列表、元组、字符串等定义相同:

  • 列表使用:[]
  • 元组使用:()
  • 字符串使用:“”
  • 集合使用:{}

集合的常用操作-修改

首先,因为集合是无序的,所以集合不支持下标索引访问;但是集合和列表一样,是允许修改的。

  • 添加新元素
    • 语法:集合.add(元素)。将指定元素,添加到集合内
    • 结果:集合本身被修改,添加了新元素
  • 移除元素
    • 语法:集合.remove(元素),将指定元素,从集合内移除
    • 结果:集合本身被修改,移除了元素
  • 从集合中随机取出元素
    • 语法:集合.pop(),从集合中随机取出一个元素
    • 结果:会得到一个元素的结果。同时集合本身被修改,元素被移除
  • 清空集合
    • 语法:集合.clear(),清空集合
    • 结果:集合本身被清空
  • 取出2个集合的差集
    • 语法:集合1.difference(集合2)
    • 功能:取出集合1和集合2的差集(集合1有而集合2没有的)
    • 结果:得到一个新集合,集合1和集合2不变
  • 消除2个集合的差集
    • 语法:集合1.difference_update(集合2)
    • 功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素
    • 结果:集合1被修改,集合2不变
  • 2个集合合并
    • 语法:集合1.union(集合2)
    • 功能:将集合1和集合2组成新集合
    • 结果:得到新集合,集合1和集合2不变

集合常用功能总结

操作说明
集合.add(元素)集合内添加一个元素
集合.remove(元素)移除集合内指定的元素
集合.pop()从集合中随机取出一个元素
集合.clear()将集合清空
集合1.difference(集合2)得到一个新集合,内含2个集合的差集;原有的2个集合内容不变
集合1.difference_update(集合2)在集合1中,删除集合2中存在的元素;集合1被修改,集合2不变
集合1.union(集合2)得到1个新集合,内含2个集合的全部元素;原有的2个集合内容不变
len(集合)得到一个整数,记录了集合的元素数量

集合的特点:

  • 可以容纳多个数据
  • 可以容纳不同类型的数据(混装)
  • 数据是无序存储的(不支持下标索引)
  • 不允许重复数据存在
  • 可以修改(增加或删除元素等)
  • 支持for循环,因为不支持下标索引,所以不支持while循环遍历
# 数据容器集合的使用
# 定义集合
my_set = {"hello","world","python","hello","world","python","hello","world","python"}
my_set_empty = set()
print(f"my_set的内容是:{my_set},类型是:{type(my_set)}")
print(f"my_set_empty的内容是:{my_set_empty},类型是:{type(my_set_empty)}")

# 添加新元素
my_set.add("and")
my_set.add("python")    # 原集合已经有python,所以无法添加
print(f"my_set添加新元素后结果是:{my_set}")

# 移除元素
my_set.remove("hello")
print(f"my_set移除元素后结果是:{my_set}")

# 随机取出一个元素
my_set = {"hello","world","python"}
element = my_set.pop()
print(f"集合被取出元素是:{element},取出元素后:{my_set}")

# 清空集合
my_set.clear()
print(f"集合被清空了,结果是:{my_set}")

# 取2个集合的差集
set1 = {1,2,3}
set2 = {1,5,6}
set3 = set1.difference(set2)
print(f"取出差集后的结果是:{set3}")
print(f"取出差集后,原有set1的内容:{set1}")
print(f"取出差集后,原有set2的内容:{set2}")

# 消除2个集合的差集
set1 = {1,2,3}
set2 = {1,5,6}
set1.difference_update(set2)
print(f"消除差集后,set1的内容:{set1}")
print(f"消除差集后,set2的内容:{set2}")

# 2个集合合并为1个
set1 = {1,2,3}
set2 = {1,5,6}
set3 = set1.union(set2)
print(f"两个集合合并后的结果是:{set3}")
print(f"合并后set1的内容:{set1}")
print(f"合并后set2的内容:{set2}")

# 统计集合元素数量
set1 = {1,2,3,4,5}
set2 = {1,2,3,4,5,1,2,3,4,5}
num = len(set1)
print(f"集合set1内的元素数量有:{num}个")
# 集合是去重的,故元素仍然只有5个
print(f"集合set2内的元素数量有:{len(set2)}个")

# 集合的遍历
# 集合不支持下标索引,不能用while循环
# 可以用for循环
set1 = {1,2,3,4,5}
for element in set1:
    print(f"集合的元素有:{element}")

**练习案例:**信息去重

# 练习
# 有如下列表对象:
my_list = ['hello','world','hello','world','and','python','and','python']
# 请:
# 定义一个空集合
my_set = set()
# 通过for循环遍历列表
for element in my_list:
    # 在for循环中将列表的元素添加至集合
    my_set.add(element)
# 最终得到元素去重后的集合对象,并打印输出
print(f"列表的内容是:{my_list}")
print(f"通过for循环后,得到的集合对象是:{my_set}")

数据容器:dict(字典、映射)

字典的定义

字典可以提供基于Key检索Value的场景实现,就像查字典一样

**字典的定义:**同样使用{},集合中存储的是一个个的单独元素,字典存储的元素是一个个的键值对,如下语法:

# 定义字典字面量
{key:value,key:value,......,key:value}
# 定义字典变量
my_dict = {key:value,key:value,......,key:value}
# 定义空字典
my_dict = {}
my_dict = dict()

字典数据的获取

字典同集合一样,不可以使用下标索引;但是字典可以通过Key值来取得对应的Value

语法:字典[Key]可以取到对应的Value

字典的嵌套

字典的Key和Value可以是任意数据类型(Key不可为字典)

那么,就表明字典是可以嵌套的

# 数据容器字典的定义
# 定义字典
my_dict1 = {'lee':99,'wang':88,'hei':77}

# 定义空字典
my_dict2 = {}
my_dict3 = dict()
print(f"dict1内容:{my_dict1},类型:{type(my_dict1)}")
print(f"dict2内容:{my_dict2},类型:{type(my_dict2)}")
print(f"dict3内容:{my_dict3},类型:{type(my_dict3)}")

# 定义重复Key的字典
my_dict1 = {'lee':99,'lee':88,'hei':77}
print(f"重复key的字典的内容:{my_dict1}")

# 从字典中基于Key获取Value
my_dict1 = {'lee':99,'wang':88,'hei':77}
score = my_dict1['lee']
print(f"lee的分数是:{score}")

# 定义嵌套字典
stu_score_dict = {
    "lee":{
    "语文":77,
    "数学":66,
    "英语":33
},"wang":{
    "语文":88,
    "数学":86,
    "英语":55
},"hei":{
    "语文":99,
    "数学":96,
    "英语":66
    }
}
print(f"学生的考试信息是:{stu_score_dict}")

# 从嵌套字典中获取数据
score = stu_score_dict["lee"]["语文"]
print(f"lee的语文分数是:{score}")

注意:

  • 键值对的Key和Value可以是任意类型(Key不可为字典)
  • 字典内Key不允许重复,重复添加等同于覆盖原有数据
  • 字典不可用下标索引,而是通过Key检索Value
字典的常用操作
  • 新增元素
    • 语法:字典[Key]=Value
    • 结果:字典被修改,新增了元素
  • 更新元素
    • 语法:字典[Key]=Value
    • 结果:字典被修改,元素被更新
    • 新增和更新元素的语法一致,字典Key不可以重复,所以对已存在的Key执行上述操作,就是更新Value值
  • 删除元素
    • 语法:字典.pop(Key)
    • 结果:获得指定Key的Value,同时字典被修改,指定Key的数据被删除
  • 清空字典
    • 语法:字典.clear()
    • 结果:字典被修改,元素被清空
  • 获取全部Key
    • 语法:字典.keys()
    • 结果:得到字典中的全部Key

字典的常用操作总结

操作说明
字典[Key]获取指定Key对应的Value值
字典[Key] = Value添加或更新键值对
字典.pop(Key)取出Key对应的Value并在字典内删除此Key的键值对
字典.clear()清空字典
字典.keys()获取字典的全部Key,可用于for循环遍历字典
len(字典)计算字典内的元素数量

字典的特点:

  • 可以容纳多个数据
  • 可以容纳不同类型的数据
  • 每一份数据是Key Value 键值对
  • 可以通过Key获取到Value,Key不可重复(重复会覆盖)
  • 不支持下标索引
  • 可以修改(增加或删除更新元素等)
  • 支持for循环,不支持while循环
# 字典的常用操作
my_dict = {"zhou":99,"lin":88,"li":77}
# 新增元素
my_dict["hei"] = 66
print(f"字典经过新增元素后的结果:{my_dict}")

# 更新元素
my_dict["zhou"] = 33
print(f"字典经过更新元素后的结果:{my_dict}")

# 删除元素
score = my_dict.pop("zhou")
print(f"字典被移除了一个元素后的结果:{my_dict},zhou的考试分数是:{score}")

# 清空元素
my_dict.clear()
print(f"字典被清空了,内容是:{my_dict}")

# 获取全部Key
my_dict = {"zhou":99,"lin":88,"li":77}
keys = my_dict.keys()
print(f"字典的全部keys是:{keys}")

# 遍历字典
# 方式1:通过获取到全部的Key来完成遍历
for key in keys:
    print(f"字典的key是:{key}")
    print(f"字典的value是:{my_dict[key]}")
# 方式2:直接对字典进行for循环,每一次循环都是直接得到Key
for key in my_dict:
    print(f"字典2的key是:{key}")
    print(f"字典2的value是:{my_dict[key]}")

# 统计字典内的元素数量
num = len(my_dict)
print(f"字典中的元素数量有:{num}个")

**练习案例:**升职加薪

# 练习
# 有如下员工信息,请使用字典完成数据的记录
my_dict = {
    "wang":{
        "部门":"科技部",
        "工资":3000,
        "级别":1
    },"zhou":{
        "部门":"市场部",
        "工资":5000,
        "级别":2
    },"lin":{
        "部门":"市场部",
        "工资":7000,
        "级别":3
    },"zhang":{
        "部门":"科技部",
        "工资":4000,
        "级别":1
    },"liu":{
        "部门":"市场部",
        "工资":6000,
        "级别":2
    }
}
print("全体员工当前信息如下:")
print(my_dict)
print()
# 自写
# 并通过for循环,对所有级别为1的员工,级别上升1级,薪水增加1000元
for name in my_dict:
    # 此处的意思是对字典的子字典直接进行更新操作
    if my_dict[name]["级别"] == 1:
        my_dict[name]["级别"] = 2
        my_dict[name]["工资"] += 1000
print(my_dict)
print()


# 参考答案
# for循环遍历字典
for name in my_dict:
    # if 条件判断符合条件员工
    # 此处的意思是在循环时候,将字典嵌套的子字典整体更新一次
    if my_dict[name]["级别"] == 1:
        # 升职加薪操作
        # 获取员工的信息字典
        employee_my_dict = my_dict[name]
        # 修改员工的信息字典
        employee_my_dict["级别"] = 2  # 级别+1
        employee_my_dict["工资"] += 1000  # 工资+1000
        # 将员工的信息更新回去
        my_dict[name] = employee_my_dict
# 输出结果
print(f"对员工进行升值加薪后的结果是:")
print(my_dict)

拓展:数据容器对比总结

数据容器可以从以下视角进行简单的分类:

  • 是否支持下标索引
    • 支持:列表、元组、字符串——序列类型
    • 不支持:集合、字典——非序列类型
  • 是否支持重复元素
    • 支持:列表、元组、字符串——序列类型
    • 不支持:集合、字典——非序列类型
  • 是否可以修改
    • 支持:列表、集合、字典
    • 不支持:元组、字符串

数据容器特点对比

列表元组字符串集合字典
元素数量支持多个支持多个支持多个支持多个支持多个
元素类型任意任意仅字符任意Key:Value (Key:除字典外任意类型;Value:任意类型)
下标索引支持支持支持不支持不支持
重复元素支持支持支持不支持不支持
可修改性支持不支持不支持支持支持
数据有序
使用场景可修改、可重复的一批数据记录场景不可修改、可重复的一批记录数据场景一串字符的记录场景不可重复的数据记录场景以Key检索Value的数据记录场景

数据容器的通用操作

数据容器的通用操作-遍历

  • 在遍历上:

    • 5类数据容器都支持for循环遍历
    • 列表、元组、字符串支持while循环,集合、字典不支持(无法下标索引)
  • 数据容器的通用统计功能

    • len(容器)——统计容器的元素个数
    • max(容器)——统计容器的最大元素
    • min(容器)——统计容器的最小元素
  • 容器的通用转换功能——通用类型转换

    • list(容器)——将给定容器转换为列表
    • str(容器)——将给定容器转换为字符串
    • tuple(容器)——将给定容器转换为元组
    • set(容器)——将给定容器转换为集合
  • 容器通用排序功能

    • sorted(容器,[reverse=True])——将给定容器进行排序

容器通用功能总览

功能描述
通用for循环遍历容器(字典是遍历Key)
max()容器内最大元素
min()容器内最小元素
len()容器元素个数
list()转换为列表
tuple()转换为元组
str()转换为字符串
set()转换为集合
sorted(序列,[reverse=True])排序,reverse=True表示降序;得到一个排好序的列表
# 数据容器的通用功能
my_list = [1,2,3,4,5]
my_tuple = (1,2,3,4,5)
my_str = "abcdefg"
my_set = {1,2,3,4,5}
my_dict = {"key1":1,"key2":2,"key3":3,"key4":4,"key5":5}

# len 元素个数
print(f"列表 元素个数有:{len(my_list)}")
print(f"元组 元素个数有:{len(my_tuple)}")
print(f"字符串元素个数有:{len(my_str)}")
print(f"集合 元素个数有:{len(my_set)}")
print(f"字典 元素个数有:{len(my_dict)}")

# max 最大元素
# 快捷键:按住shift + alt + 拖动鼠标,同时进行行字相同替换
print(f"列表 最大的元素是:{max(my_list)}")
print(f"元组 最大的元素是:{max(my_tuple)}")
print(f"字符串最大的元素是:{max(my_str)}")
print(f"集合 最大的元素是:{max(my_set)}")
print(f"字典 最大的元素是:{max(my_dict)}")

# min 最小元素
print(f"列表 最小的元素是:{min(my_list)}")
print(f"元组 最小的元素是:{min(my_tuple)}")
print(f"字符串最小的元素是:{min(my_str)}")
print(f"集合 最小的元素是:{min(my_set)}")
print(f"字典 最小的元素是:{min(my_dict)}")

# 类型转换:容器转列表
print(f"列表转列表的结果是:{list(my_list)}")
print(f"元组转列表的结果是:{list(my_tuple)}")
print(f"字符串转列表结果是:{list(my_str)}")
print(f"集合转列表的结果是:{list(my_set)}")
print(f"字典转列表的结果是:{list(my_dict)}")

# 类型转换:容器转元组
print(f"列表转元组的结果是:{tuple(my_list)}")
print(f"元组转元组的结果是:{tuple(my_tuple)}")
print(f"字符串转元组结果是:{tuple(my_str)}")
print(f"集合转元组的结果是:{tuple(my_set)}")
print(f"字典转元组的结果是:{tuple(my_dict)}")

# 类型转换:容器转字符串
print(f"列表转字符串的结果是:{str(my_list)}")     # 已经转换成'[1, 2, 3, 4, 5]'
print(f"元组转字符串的结果是:{str(my_tuple)}")    # 已经转换成'(1, 2, 3, 4, 5)'
print(f"字符串转字符串组结果是:{str(my_str)}")
print(f"集合转字符串的结果是:{str(my_set)}")
print(f"字典转字符串的结果是:{str(my_dict)}")

# 类型转换:容器转集合        # 集合数据无序性,无重复性
print(f"列表转集合的结果是:{set(my_list)}")
print(f"元组转集合的结果是:{set(my_tuple)}")
print(f"字符串转集合结果是:{set(my_str)}")
print(f"集合转集合的结果是:{set(my_set)}")
print(f"字典转集合的结果是:{set(my_dict)}")

# 进行容器的排序sorted
my_list = [3,1,2,5,4]
my_tuple = (3,1,4,5,2)
my_str = "cbadfeg"
my_set = {3,1,4,5,2}
my_dict = {"key3":3,"key1":1,"key2":2,"key5":5,"key4":4}
print(f"列表对象的排序结果是:{sorted(my_list)}")
print(f"元组对象的排序结果是:{sorted(my_tuple)}")
print(f"字符串对象排序结果是:{sorted(my_str)}")
print(f"集合对象的排序结果是:{sorted(my_set)}")
print(f"字典对象的排序结果是:{sorted(my_dict)}")

print(f"列表对象的反向排序结果是:{sorted(my_list,reverse=True)}")
print(f"元组对象的反向排序结果是:{sorted(my_tuple,reverse=True)}")
print(f"字符串对象反向排序结果是:{sorted(my_str,reverse=True)}")
print(f"集合对象的反向排序结果是:{sorted(my_set,reverse=True)}")
print(f"字典对象的反向排序结果是:{sorted(my_dict,reverse=True)}")

**拓展:**字符串大小比较

本质上是ASCⅡ码进行的比较

每一个字都都能对应上一个:数字的码值

字符串进行比较就是基于数字的码值大小进行比较的。

**字符串比较:**字符串是按位比较,也就是一位位进行对比,只要有一位大,那么整体就大

# 字符串大小比较
# abc比较abd
print(f"abd大于abc,结果:{'abd'>'abc'}")
# a比较ab
print(f"ab大于a,结果:{'ab'>'a'}")
# a比较A
print(f"a大于A,结果:{'a'>'A'}")
# key1比较key2
print(f"key2大于key1,结果:{'key2'>'key1'}")

从头到尾,一位位比较,其中一位大,后面就无需比较了。通过ASCⅡ码值确定字符对应的码值数字来确定大小。

第七章 函数进阶

函数多返回值

多个返回值

def test_return():
    return 1,2
x,y = test_return()
print(x)	# 结果1
print(y)	# 结果2

按照返回值的顺序,写对应顺序的多个变量接收即可

变量之间用逗号隔开

支持不同类型的数据return

# 函数的多返回值示例
# 使用多个变量,接收多个返回值
def test_return():
 return 1,"hello",True
x,y,z = test_return()
print(x)
print(y)
print(z)

函数多种传参方式

函数参数种类

使用方式上的不同,函数有4种常见参数使用方式:

位置参数

关键字参数

缺省参数

不定长参数

  • 位置参数
    • 位置参数:调用函数时根据函数定义的参数位置来传递参数
    • 注意:传递的参数和定义的参数的顺序及个数必须一致
  • 关键字参数
    • 关键字参数:函数调用时通过 “键=值” 形式传递参数
    • 作用:可以让函数更加清晰、容易使用,同时也消除了参数的顺序需求
    • 注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
  • 缺省参数
    • 缺省参数:也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值
    • 注意:所有位置参数必须出现在默认参数前,包括函数定义和调用
    • 作用:当调用函数时没有传递参数,就会使用默认是缺省参数对应的值
    • PS:函数调用时,如果为缺省参数传值则修改默认参数值,否则使用这个默认值
  • 不定长参数
    • 不定长参数:也叫可变参数,用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
    • 作用:当调用函数时不确定参数个数时,可以使用不定长参数
    • 不定长参数的类型:
      • 位置传递
        • 语法:def user_info(*args):
        • 注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
      • 关键字传递
        • 语法:def user_info(**kwargs):
        • 注意:参数是 ”键=值“ 形式的情况下,所有的 ”键=值“ 都会被kwargs接收,同时会根据 ”键=值“ 组成字典
# 多种传参的形式
def user_info(name,age,gender):
    print(f"姓名是:{name},年龄是:{age},性别是:{gender}")

# 位置参数-默认使用形式
user_info("小明",20,'男')

# 关键字参数
user_info(name='小王',age=21,gender='男')
user_info(age=10,gender='女',name='潇潇')  # 关键字传参可以不按照参数的定义顺序传参
user_info('田田',gender='女',age=18)

# 缺省参数(默认值)
def user_info(name,age,gender='男'): # 设置默认值时,必须保证有默认值之后的全部有默认值
    print(f"姓名是:{name},年龄是:{age},性别是:{gender}")
user_info('小天',13)
user_info('小天',13,gender='女')

# 不定长-位置不定长,*号
# 不定长定义的形式参数会作为元组存在,接收不定长数量的参数传入
def user_info(*args):
    print(f"args参数的类型是:{type(args)},内容是:{args}")
user_info(1,2,3,'tom')

# 不定长-关键字不定长,**号
def user_info(**kwargs):
    print(f"args参数的类型是:{type(kwargs)},内容是:{kwargs}")
user_info(name='小王',age=21,gender='男')

匿名函数

函数作为参数传递
def test_func(compute):
    result = compute(1,2)
    print(result)
def compute(x,y):
    return x+y
test_func(compute)

函数compute,作为参数,传入了test_func函数中使用

test_func需要一个函数作为参数传入,这个函数需要接收2个数字进行计算,计算逻辑由这个被传入函数决定

compute函数接收2个数字对其进行计算,compute函数作为参数,传递给了test_func函数使用

最终,在test_func函数内部,由传入的compute函数,完成了对数字的计算操作

总结:

这是一种计算逻辑的传递,而非数据的传递。像上述代码,相加、减、乘、除等任何逻辑都可以自行定义并作为函数传入。

# 函数作为参数传递
# 定义一个函数,接受另一个函数作为传入参数
def test_func(compute):
    result = compute(1,2)   # 确定compute是函数
    print(f"compute参数的类型是:{type(compute)}")
    print(f"计算结果:{result}")
# 定义一个函数,准备作为参数传入另一个函数
def compute(x,y):
    return x+y
# 调用,并传入函数
test_func(compute)

总结:

  • 函数本身是可以作为参数,传入另一个函数中进行使用的
  • 将函数传入的作用在于:传入计算逻辑,而非传入数据
lambda匿名函数

函数的定义中

  • def关键字,可以定义带有名称的函数
  • lambda关键字,可以定义匿名函数(无名称)

有名称的函数,可以基于名称重复使用

无名称的匿名函数,只可临时使用一次

匿名函数定义语法:lambda 传入参数:函数体(一行代码)

  • lambda 是关键字,表示定义匿名函数

  • 传入参数表示匿名函数的形式参数,如:x,y表示接收2个形式参数

  • 函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码

  • PS:使用def和使用lambda,定义的函数功能完全一致,只是lambda关键字定义的函数是匿名的,只能用一次,无法二次使用

# lambda匿名函数
# 定义一个函数,接收其它函数输入
def test_func(compute):
    result = compute(1,2)
    print(f"结果是:{result}")
# 通过lambda匿名函数的形式,将匿名函数作为参数传入
def add(x,y):
    return x+y
test_func(add)
test_func(lambda x,y:x+y)

注意事项:

  • 匿名函数用于临时构建一个函数,只用一次的场景
  • 匿名函数的定义中,函数体只能写一行代码,如果函数体要写多行代码,不可用lambda匿名函数,应使用def定义带名函数

第八章 文件操作

文件的编码

文件编码

编码技术:翻译的规则,记录了如何将内容翻译成二进制,以及如何将二进制翻译回可识别内容

计算机中有许多可用编码:UTF-8、GBK、Big5等,不同的编码将内容翻译成二进制也是不同的

查看文件编码:

可以使用Windows系统自带的记事本,打开文件后,即可看出文件的编码是什么。UTF-8是目前全球通用的编码格式

文件的读取

一篇文章、一段视频、一个可执行程序,都可以被保存为一个文件,并赋予一个文件名。

文件可分为文本文件,视频文件,音频文件,图像文件,可执行文件等多种类别。

文件操作主要包括打开,关闭,读,写等操作

**文件的操作步骤:**大概可以分为三个步骤(简称文件操作三步走)

  • 打开文件
  • 读写文件
  • 关闭文件

注意:可以只打开和关闭文件,不进行任何读写

open()打开函数

  • 使用open函数,可以打开一个已经存在的文件,或者创建一个新文件

    • 语法:open(name,mode,encoding)

    • name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)

    • mode:设置打开文件的模式(访问模式):只读、写入、追加等

      • 模式描述
        r以只读方式打开文件,文件的指针将会放在文件的开头。这是默认模式。
        w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除。如果该文件不存在,创建新文件。
        a打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    • encoding:编码格式(推荐使用UTF-8)

  • 读操作相关方法

    • read()方法:文件对象.read(num)

      • num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中的所有数据。
    • readlines()方法:

      • readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
    • readline()方法:

      • 一次读取一行内容
    • for循环读取文件行

      • for line in open("python.txt","r"):
            print(line)
        
      • 每一个 line 临时变量,就记录了文件的一行数据

    • close()关闭文件对象

      • f = open("python.txt","r")
        f.close()
        
      • 最后通过close,关闭文件对象,也就是关闭对文件的占用

      • 如果不调用close,同时程序没有停止运行,那么这个文件将一直被python程序占用

    • with open 语法

      • with open("python.txt","r") as f:
            f.readlines()
        # 通过在with open的语句块中对文件进行操作
        # 可以在操作完成后自动关闭close文件,避免遗忘掉close方法
        

操作汇总

操作功能
文件对象 = open(file,mode,encoding)打开文件获得文件对象
文件对象:read(num)读取指定num长度字节;不指定num读取全部文件
文件对象.readline()读取一行
文件对象.readlines()读取全部行,得到列表
for line in 文件对象for 循环文件行,一次循环得到一行数据
文件对象.close()关闭文件对象
with open(file,mode,encoding) as f通过 with open 语法打开文件,可以自动关闭
# 对文件的读取
# 打开文件
import time # 使用time.sleep(50000)需要的
f = open("D:/python 代码/测试.txt","r",encoding="UTF-8")
print(type(f))

# 读取文件-read()
print(f"读取10个字节的结果:{f.read(10)}")
# 只要文件打开后进行读操作,都会相当于有一个指针续接上一次读取的地方
print(f"read方法读取全部内容结果:{f.read()}")
print("---------------------------------")

# 读取文件-readlines()
lines = f.readlines()   # 读取文件的全部行,封装到列表中
print(f"lines对象的类型是:{type(lines)}")
print(f"lines的内容是:{lines}")

# # 读取文件-readline()
line1 = f.readline()
line2 = f.readline()
line3 = f.readline()
print(f"第1行数据是:{line1}")
print(f"第2行数据是:{line2}")
print(f"第3行数据是:{line3}")

# for循环读取文件行
for line in f:
    print(f"每一行数据是:{line}")

# 文件的关闭
# time.sleep(50000) # 程序睡眠函数,此时文件无法关闭
f.close()
# 如果睡眠放在文件关闭后,则文件可以正常关闭

# with open 语法操作文件
# 操作语句执行完后,文件会自动关闭
with open("D:/python 代码/测试.txt","r",encoding="UTF-8")as f:
    for line in f:
        print(f"每一行数据是:{line}")
time.sleep(50000)

总结:

  • 操作文件需要通过open函数打开文件得到文件对象
  • 文件读取完成后,要使用文件对象.close()方法关闭文件对象,否则文件会被一直占用

**练习:**单词计数

# 练习
# 通过windows的文本编辑器软件,将如下内容复制并保存到:word.txt,文件可以存储任意位置。
# 通过文件读取操作,读取此文件,统计itheima单词出现次数
# 打开文件,以读取模式打开
f = open("D:/python 代码/word.txt","r",encoding="UTF-8")
# 方式1:读取全部内容,通过字符串count方法统计itheima单词数量
content = f.read()
count = content.count("itheima")
print(f"itheima在文件中出现了:{count}次")

# 方式2:读取内容,一行行读取
count = 0   # 使用count变量来累计字符串出现次数
for line in f:
    line = line.strip() # 去除开头和结尾的空格以及换行符
    words = line.split(" ")
    for word in words:
        if word == "itheima":
            count += 1  # 单词符合,count+1
# 判断单词出现次数并累计
print(f"itheima在文件中出现了:{count}次")
# 关闭文件
f.close()

文件的写入

写操作快速入门

# 1.打开文件
f = open('python.txt','w')

# 2.文件写入
f.write('hello world')

# 3.内容刷新
f.flush()

注意:

直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区

当调用flush的时候,内容会真正写入文件

这样做是避免频繁的操作硬盘,导致效率下降(攒一堆,一次性写磁盘)

# 文件的写入
# 打开文件,不存在的文件
f = open("D:/python 代码/write_test.txt","w",encoding="UTF-8")
# write写入
f.write("hello world")  # 内容写入到内存中
# flush刷新
f.flush()   # 将内存中积攒的内容,写入到硬盘的文件中
# close关闭
f.close()   # close方法,内置了flush的功能,如果进行close,可以省略flush

# 打开一个存在的文件
# 文件存在,会清空里面内容,重新进行写入
f = open("D:/python 代码/write_test.txt","w",encoding="UTF-8")
# write写入,flush刷新
f.write("你好,世界!")
# close关闭
f.close()

总结:

  • 写入文件使用open函数的 "w" 模式进行写入
  • 写入的方法有:
    • write(),写入内容
    • flush(),刷新内容到硬盘中
  • 注意事项:
    • w模式,文件不存在,会创建新文件
    • w模式,文件存在,会清空原有内容,重新写入
    • close()方法,带有flush()的功能

文件的追加

追加写入操作快速入门

# 1.打开文件,通过a模式打开即可
f = open('python.txt','a')

# 2.文件写入
f,write('hello world')

# 3.内容刷新
f.flush()

注意:

a模式,文件不存在会创建文件

a模式,文件存在会在最后,追加写入文件

# 文件的追加写入
# 打开文件,不存在的文件
f = open("D:/python 代码/追加_test.txt","a",encoding="UTF-8")
# write写入
f.write("hello world")
# flush刷新
f.flush()
# close关闭
f.close()

# 打开一个存在的文件
f = open("D:/python 代码/追加_test.txt","a",encoding="UTF-8")
# write写入,flush刷新
f.write("\n你好,世界")
# close关闭
f.close()

总结:

  • 追加写入文件使用open函数的 "a"模式进行写入
  • 追加写入的方法有(和w模式一致)
    • write(),写入内容
    • flush(),刷新内容到硬盘中
  • 注意事项:
    • a模式,文件不存在,会创建新文件
    • a模式,文件存在,会在原有内容后面继续写入
    • 可以使用 ”\n“ 来写出换行符

文件操作综合案例

# 综合案例
# 需求分析:有一份账单文件,记录了消费收入的具体记录。将内容复制并保存为bill.txt文件
# 要做的是:
# 读取文件
# 将文件写出到bill.txt.bak文件作为备份
# 同时,将文件内标记为测试的数据行丢弃
# 实现思路:
# open 和 r 模式打开一个文件对象,并读取文件
fr = open("D:/python 代码/bill.txt","r",encoding="UTF-8")
# open 和 w 模式打开另一个文件对象,用于文件写出
fw = open("D:/python 代码/bill.txt.bak","w",encoding="UTF-8")
# for 循环内容,判断是否是测试,不是测试就write写出,是测试就continue跳过
title = fr.readline()
fw.write(title)
for line in fr:
    line = line.strip() # 清理掉字符串的开头和结尾的空格和换行符
    if line.split(",")[-1] == "测试":
        continue
    # 将内容写出去
    fw.write(line)
    # 由于前面对内容进行了清楚空格和换行符的strip操作,所以需要手动写换行符
    fw.write("\n")
# 将两个文件对象均close
fr.close()
fw.close()

第九章 异常、模块与包

了解异常

什么是异常?

当检测到一个错误时,python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”,也就是BUG

# 主动写一段错误代码,演示异常的出现
# 通过open,读取一个不存在的文件
open("C:/测试1.txt","r")

异常的捕获方法

为何要捕获异常?

世界上没有完美的程序,任何程序在运行的过程中,都有可能出现异常,导致程序无法完美运行下去。

我们要做的是在力所能及范围内,对可能出现的bug,进行提前准备、提前处理

这种行为我们称为:异常处理(捕获异常)

遇到BUG,会有两种情况:①整个程序因为BUG停止运行;②对BUG进行提醒,整个程序继续运行

捕获异常的作用在于:提前假设某处会出现异常,做好提前准备,当真的出现异常的时候,可以有后续手段。

捕获常规异常

基本语法

try:
 可能发生错误的代码
except:
 如果出现异常执行的代码

捕获指定异常

基本语法:

try:
 print(name)
except NameError as e:
 print('name变量名称未定义错误')

注意:

① 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常

② 一般 try 下方只放一行尝试执行的代码

捕获多个异常

当捕获多个异常时,可以把要捕获的异常类型的名字,放到except后,并使用元组的方式进行书写

try:
 print(1/0)
except(NameError,ZeroDivisionError) as e:
 print('ZeroDivision错误...')

异常else

else表示的是如果没有异常要执行的代码

try:
 print(1)
except Exception as e:
 print(e)
else:
 print('我是else,是没有异常的时候执行的代码')

异常的finally

finally表示的是无论是否异常都要执行的代码,例如关闭文件。

try:
 f = open('test.txt','r')
except Exception as e:
 f = open('test.txt','w')
else:
 print('没有异常')
finally:
 f.close()
# 捕获异常
# 基本捕获语法
try:
    f = open("D:/python 代码/不存在的_test.txt","r",encoding="UTF-8")
except:
    print("出现异常了,因为文件不存在,将r模式改为w模式")
    f = open("D:/python 代码/不存在的_test.txt","w",encoding="UTF-8")

# 捕获指定的异常
try:
    print(name)
    # 1/0
except NameError as e:
    print("出现了变量未定义的异常")
    print(e)

# 捕获多个异常
try:
    # 1/0
    print(name)
except(NameError,ZeroDivisionError) as e:
    print("出现了变量未定义或除以0的异常")
# 未正确设置捕获异常类型,将无法捕获异常

# 捕获所有异常
try:
    # print("hello")
    # 1/0
    f = open("D:/python 代码/123test.txt", "r", encoding="UTF-8")
except Exception as e:  # 省事写法就是except:  # 有异常会执行
    print("出现异常了")
    f = open("D:/python 代码/123test.txt", "w", encoding="UTF-8")
else:   # 没有异常会执行
    print("没有异常产生")
finally:    # 有没有异常,都会执行
    print("finally,有没有异常都会执行")
    f.close()

总结:

  • 捕获异常的原因:当异常出现的时候,提供解决方式,而不是任由其导致程序无法运行

  • try:
        可能要发生异常的语句
    except [异常 as 别名:]
    	出现异常的准备手段
    [else:]
    	未出现异常时应做的事情
    [finally:]
    	不管出不出现异常都会做的事情
    
  • 如果想要不管什么类型的异常都能捕获到,可以使用:

    • except:
    • except Exception:
    • 这两种方式捕获全部异常

异常的传递

异常是具有传递性的

# 异常的传递性
# 定义一个出现异常的方法
def func1():
    print("func1 开始执行")
    num = 1/0   # 肯定有异常,除0异常
    print("func1 结束执行")
# 定义一个无异常的方法,调用上面方法
def func2():
    print("func2 开始执行")
    func1()
    print("func2 结束执行")
# 定义一个方法,调用上面的方法
def main():
    try:
        func2()
    except Exception as e:
        print(f"出现异常了,异常的信息是:{e}")
main()

提示:当所有函数都没有捕获异常的时候,程序就会报错

python模块

模块导入

什么是模块

python 模块 ,是一个 python 文件,以 .py 结尾。模块能定义函数,类和变量,模块里也能包含可执行的代码。

**模块的作用:**python中有很多各种不同的模块,每一个模块都可以帮助我们快速实现一些功能,比如实现和事件相关的功能就可以使用 time模块。可以认为一个模块就是一个工具包,每一个工具包中都有各种不同的工具供我们使用进而实现各种不同的功能。

模块的导入方式

模块在使用前需要先导入,导入的语法如下:

[from 模块名] import [模块|类|变量|函数|*][as 别名]

常用的组合形式如:

  • import 模块名
  • from 模块名 import 类、变量、方法等
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名

import模块名

基本语法:

import 模块名
import 模块名1,模块名2
模块名.功能名()

from 模块名 import 功能名

基本语法

from 模块名 import 功能名
功能名()

**from 模块名 import ***

基本语法:(导入time模块中所有的方法)

from 模块名 import *
功能名()

as定义别名

基本语法:

# 模块定义别名
import 功能名 as 别名
# 功能定义别名
from 模块名 import 功能 as 别名
# 模块导入
# 使用import导入time模块使用sleep功能(函数)
import time # 导入python内置的time模块,(time.py这个代码文件)
print("你好")
time.sleep(5)   # 通过 . 就可以使用模块内部的全部功能(类、函数、变量)
print("我好")

# 使用from导入time的sleep功能(函数)
from time import sleep
print("你好")
sleep(3)
print("我好")

# 使用 * 导入time模块的全部功能
from time import*   # *表示全部的意思
print("你好")
sleep(3)
print("我好")

# 使用as给特定功能加上别名
import time as t
print("你好")
t.sleep(3)
print("我好")
from time import sleep as s
print("你好")
s(3)
print("我好")

总结

模块就是一个python代码文件,内涵类、函数、变量等,我们可以导入进行使用

[from 模块名] import [模块|类|变量|函数|*][as 别名]

注意事项:

  • from可以省略,直接import即可
  • as别名可以省略
  • 通过 " . " 来确定层级关系
  • 模块的导入一般写在代码文件的开头位置
自定义模块

制作自定义模块

需要一些个性化的模块,可以通过自定义模块实现,即自己制作一个模块

注意:每个python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块必须要符合标识符命名规则

PS:当导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是后面导入的模块的功能

测试模块

在开发中,开发人员编写完一个模块后,为了让模块能够在项目中达到预期效果,开发人员会自行在py文件中添加一些测试信息。

问题是:无论当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自行执行 ’test‘ 函数的调用

解决方法:

# 只在当前文件中调用该函数,其他导入文件内不符合该条件,则不执行test函数调用
if __name__ == '__main__':
 test(1,2)

__all__变量

如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素

# 自定义模块
# 导入自定义模块使用
#import my_modle
#my_modle.test(1,2)
# from my_modle1 import test
# test(1,2)

# 导入不同模块的同名功能
# from my_modle1 import test
# from my_modle2 import test
# test(1,2)

# __main__变量
# from my_modle1 import test

# __all__变量
from my_modle1 import *
testA(1,2)
# testB(1,2)

总结:

自定义模块并导入的方法:通过import、from关键字和导入python内置模块一样导入即可使用

__main__变量的功能:if name == ‘main’ 表示只有当程序是直接执行的才会进入if内部,如果是被导入的,则if无法进入

注意事项:

  • 不同模块,同名的功能,如果都被导入,那么后导入的会覆盖先导入的
  • __all__变量可以控制import*的时候哪些功能可以被导入

python包

自定义包

什么是python包

从物理上看,包就是一个文件夹,在该文件夹下包含了一个__init__.py文件,该文件夹可用于包含多个模块文件

从逻辑上看,包的本质依然是模块

**包的作用:**当我们的模块文件越来越多时,包可以帮助我们管理这些模块,包的作用就是包含多个模块,但包的本质依然是模块

快速入门

① 新建包’my_package’

② 新建包内模块:‘my_module1’ 和 ‘my_module2’

③ 模块代码如下

# my_module1模块中
print(1)
def info_print1():
 print('my_module1')

# my_module2模块中
print(2)
def info_print2():
 print('my_module2')

Pycharm中的基本步骤:[New]——[Python Package]——输入包名——[OK]——新建功能模块(有联系的模块)

​ 注意:新建包后,包内部会自动创建__init__.py文件,这个文件控制着包的导入行为

导入包

  • 方式一:
    • import 包名.模块名
    • 包名.模块名.目标
  • 方式二:
    • PS:必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表
    • from 包名 import *
    • 模块名.目标
    • 注意:__all__针对的是from...import *这种方式,对import xxx这种方式无效
# python的包
# 创建一个包
# 导入自定义的包中的模块,并使用
# 方法1
# import my_package.my_module1
# import my_package.my_module2
# my_package.my_module1.info_print1()
# my_package.my_module2.info_print2()
# 方法2
# from my_package import my_module1
# from my_package import my_module2
# my_module1.info_print1()
# my_module2.info_print2()
# 方法3
# from my_package.my_module1 import info_print1
# from my_package.my_module2 import info_print2
# info_print1()
# info_print2()

# 通过__all__变量,控制import *
from my_package import *
my_module1.info_print1()
# my_module2.info_print2() all变量里只导入了模块1

总结:

  • 包就是一个文件夹,里面可以存放许多的python的模块(代码文件),通过包,在逻辑上将一批模块归为一类,方便使用
  • __init__.py文件的作用是创建包会默认自动创建的文件,通过这个文件来表示一个文件夹是python的包,而非普通的文件夹。
  • __all__变量作用:同模块中学习到的是一个作用,控制 import * 能够导入的内容
安装第三方python包

什么是第三方包

一个包,就是一堆同类型功能的集合体

在python程序生态中,有许多非常多的第三方包(非python官方),可以极大的帮助我们提高开发效率,如:

  • 科学计算中常用的:numpy包
  • 数据分析中常用的:pandas包
  • 大数据计算中常用的:pyspark、apache-flink包
  • 图形可视化常用的:matplotlib、pyecharts
  • 人工智能常用的:tensorflow

这些第三方包,极大的丰富了python的生态,提高了开发效率

但是由于是第三方,所以python没有内置,所以需要我们安装他们才可以导入使用

安装第三方包 - pip

只需要使用python内置的pip程序即可

打开命令提示符程序,在里面输入:

pip install 包名称

即可通过网络快速安装第三方包

pip的网络优化

由于pip是连接的国外的网站进行包的下载,所以有的时候网速会很慢

我们通过如下命令,让其链接国内的网站进行包的安装:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称

https://pypi.tuna.tsinghua.edu.cn/simple 是清华大学提供的一个网站,可供pip程序下载第三方包

安装第三方包 - PyCharm

PyCharm也提供了安装第三方包的功能

总结:

  • 第三方包就是非python官方内置的包,可以安装他们扩展功能,提高开发效率
  • 安装方式
    • 在命令提示符内:
      • pip install 包名称
      • pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
    • 在PyCharm中安装

综合案例

练习:自定义工具包

创建一个自定义包,名称为:my_utils(我的工具),在包内提供2个模块

  • str_util.py(字符串相关,内容:)

    • 函数:str_reverse(s),接受传入字符串,将字符串反转返回
    • 函数:substr(s,x,y),按照下标x和y,对字符串进行切片
  • file_util.py(文件处理相关工具,内容:)

    • 函数:print_file_info(file_name),接受传入文件的路径,打印文件的全部内容,如果不存在则捕获异常,输出提示信息,通过finally关闭文件对象

    • 函数:append_to_file(file_name,data),接收文件路径以及传入数据,将数据追加写入文件中

      构建出包后,尝试着用一用自己编写的工具包

# 练习:自定义工具包
# 创建一个自定义包,名称为:my_utils(我的工具)
# 构建出包后,尝试着用一用自己编写的工具包
import my_utils.str_util        # 调用包的方式1
from my_utils import file_util  # 调用包的方式2

print(my_utils.str_util.str_reverse("hello world"))
print(my_utils.str_util.substr("hello",1,4))

file_util.print_file_info("D:/python 代码/测试.txt")
file_util.append_to_file("测试.txt","继续测试哈哈哈")
file_util.print_file_info("D:/python 代码/测试.txt")
# file_util.py(文件处理相关工具,内容:)
# 函数:print_file_info(file_name),接受传入文件的路径,打印文件的全部内容,
#       如果不存在则捕获异常,输出提示信息,通过finally关闭文件对象
def print_file_info(file_name):
    """
    功能:将给定路径的文件内容输出到控制台中
    :param file_name: 即将读取的文件路径
    :return: None
    """
    f = None
    try:
        f = open(file_name,"r",encoding="UTF-8")
        content = f.read()
        print("文件的全部内容如下:")
        print(content)
    except Exception as e:
        print(f"程序出现异常,原因是:{e}")
    finally:
        if f:   # 如果变量是None,表示False,如果有任何内容,就是True
            f.close()
# 函数:append_to_file(file_name,data),接收文件路径以及传入数据,将数据追加写入文件中
def append_to_file(file_name,data):
    """
    功能:将指定数据追加到文件中
    :param file_name: 指定文件的路径
    :param data: 指定的数据
    :return: None
    """
    f = open(file_name,"a",encoding="UTF-8")
    f.write(data)
    f.write("\n")
    f.close()
if __name__ == '__main__':
    # print_file_info("D:/python 代码/测试.txt")
    append_to_file("D:/python 代码/测试.txt","综合案例")
    print_file_info("D:/python 代码/测试.txt")
# str_util.py(字符串相关,内容:)
# 函数:str_reverse(s),接受传入字符串,将字符串反转返回
def str_reverse(s):
    """
    将字符串完成反转操作
    :param s: 将被反转的字符串
    :return: 反转后的字符串
    """
    return s[::-1]  # 运用数据容器切片概念将字符串逆转
# 函数:substr(s,x,y),按照下标x和y,对字符串进行切片
def substr(s,x,y):
    """
    按照给定的下标完成给定字符串的切片
    :param s: 即将被切片的字符串
    :param x: 切片开始下标
    :param y: 切片结束下标
    :return: 切片完成后的下标
    """
    return s[x:y]
if __name__ == '__main__':
    name = "hello world"
    print(str_reverse(name))
    print(substr(name,1,7))

第十章 综合案例-折线图

数据可视化 - 折线图可视化

实现效果一:折线统计图数据可视化

实现效果二:地图信息可视化

实现效果三:动态柱状图

数据来源

  • 课程来自黑马程序员,案例数据来自《百度疫情实时大数据报告》,及公开的全球各国GDP数据
  • 使用的技术
    • Echarts是个由百度开源的数据可视化,凭借着良好的交互性,图标设计,得到开发者的认可。而python富有表达能力的语言,很适合用于数据处理。当数据分析遇上数据可视化时 pyecharts 诞生了

json数据格式

什么是json

  • JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装
  • JSON本质上是一个带有特定格式的字符串
  • **主要功能:**json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互,类似于:
    • 国际通用语言-英语
    • 中国56个民族不同地区的通用语言-普通话

json有什么用

  • 各种编程语言存储数据的容器不尽相同,在python中有字典dict这样的数据类型,而其它语言可能没有对应的字典
  • 为了让不同的语言能够相互通用的互相传递数据,json就是一种非常良好的中转数据格式

json格式数据转化

json格式的数据要求很严格

# json数据的格式可以是:
{"name":"admin","age":18}

# 也可以是:
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"lee","age":20}]

python数据和json数据的相互转化

# 导入json模块
import json

# 准备符合格式json格式要求的python数据
data = [{"name":"admin","age":18},{"name":"root","age":16}]

# 通过json.dumps(data)方法把python数据转化为了json数据
data = json.dumps(data)

# 通过json.loads(data)方法把json数据转化为了python数据
data = json.loads(data)
# json数据和python字典的相互转换
import json
# 准备列表,列表内每一个元素都是字典,将其转换为json
data = [{"name":"张","age":18},{"name":"胡","age":21},{"name":"lee","age":32}]
json_str = json.dumps(data,ensure_ascii=False)
print(type(json_str))
print(data)
print(json_str) # 中文会涉及编码问题,用ensure_ascii=False解决
# 准备字典,将字典转换为json
d = {"name":"周杰伦","addr":"上海"}
json_str = json.dumps(d,ensure_ascii=False)
print(type(json_str))
print(json_str)
# 将json字符串转换为python数据类型[{k:v,k:v},{k:v,k:v}]
s = '[{"name":"admin","age":18},{"name":"root","age":16},{"name":"lee","age":20}]'
l = json.loads(s)
print(type(l))
print(l)
# 将json字符串转换为python数据类型{k:v,k:v}
s = '{"name":"周杰伦","addr":"上海"}'
d = json.loads(s)
print(type(d))
print(d)

总结:

  • json:是一种轻量级的数据交互格式,采用完全独立于编程语言的文本格式来存储和表示数据(就是字符串)
    • python语言使用json有很大优势,因为:json无非就是一个单独的字典或一个内部元素都是字典的列表
    • 所以json可以直接和python的字典或列表进行无缝转换
  • json格式数据转化
    • 通过json.dumps(data)方法把python数据转化为json数据
      • data = json.dumps(data)
      • 如果有中文可以带上:ensure_ascii=False参数来确保中文正常转换
    • 通过json.loads(data)方法把json数据转化为了python列表或字典
      • data = json.loads(data)

pyecharts模块介绍

pyecharts模块

  • 想要做出数据可视化效果图,可以借助pyecharts模块来完成

官网:pyecharts.org

可视化画廊代码官网:gallery.pyecharts.org

pyecharts模块安装

  • 使用前面学过的pip命令即可快速安装PyEcharts模块
  • pip install pyecharts

总结:

  • 开发可视化图表使用的技术栈是:Echarts框架的python版本:PyEcharts包
  • 如何安装PyEcharts包:pip install pyecharts
  • 查看官方示例:
    • 打开官方画廊:gallery.pyecharts.org

pyecharts快速入门

  • 基础折线图
# 导包,导入Line功能构建折线图对象
from pyecharts.charts import Line

# 得到折线图对象
line = Line()
# 添加x轴数据
line.add_xaxis(["中国","美国","英国"])
# 添加y轴数据
line.add_yaxis("GDP",[30,20,10])
# 生成图表
line.render()

pyecharts有哪些配置选项

  • pyecharts模块中有很多的配置选项,常用到2个类别的选项:
    • 全局配置选项
    • 系列配置选项

set_global_opts方法

  • 全局配置选项,可以通过set_global_opts方法来进行配置
# pyecharts演示
# 导包
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,20,10])
#设置全局配置项,通过set_global_opts方法设置
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)
)
# 通过render方法,将代码生成为图像
line.render()

总结:

  • pyecharts模块中有很多的配置选项,常用到三个类别的选项:
    • 全局配置选项
    • 系列配置选项
  • 全局配置项的作用
    • 配置图表的标题
    • 配置图例
    • 配置鼠标移动效果
    • 配置工具栏
    • 等整体配置项

数据处理

通过第三方工具快速查看大量数据的json数据格式,网址:ab173

用第三方工具去处理量大的数据,进行拆分,用以分析层级关系。

创建折线图

# 可视化需求1:折线图开发
import json
from pyecharts.charts import Line
from pyecharts.options import TitleOpts,LabelOpts

# 处理数据
f_us = open("D:/python 代码/可视化案例数据/折线图数据/美国.txt",'r',encoding="UTF-8")
us_data = f_us.read()   # 美国的全部内容
f_jp = open("D:/python 代码/可视化案例数据/折线图数据/日本.txt",'r',encoding="UTF-8")
jp_data = f_jp.read()   # 日本的全部内容
f_in = open("D:/python 代码/可视化案例数据/折线图数据/印度.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轴数据
line.add_xaxis(us_x_data)   # x轴是共用的,所以使用一个国家的数据即可
# 添加y轴数据
line.add_yaxis("美国确诊人数",us_y_data,label_opts=LabelOpts(is_show=False))  # 添加美国的y轴数据
line.add_yaxis("日本确诊人数",jp_y_data,label_opts=LabelOpts(is_show=False))  # 添加日本的y轴数据
line.add_yaxis("印度确诊人数",in_y_data,label_opts=LabelOpts(is_show=False))  # 添加印度的y轴数据

# 设置全局选项
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()

第十一章 综合案例-地图

数据可视化 - 地图可视化

基础地图使用

基础地图演示

from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
map = Map()
data = [
 ("北京",99),
 ("上海",199),
 ("湖南",299),
 ("台湾",199),
 ("安徽",299),
 ("广州",399),
 ("湖北",599),
]
map.add("地图",data,"china")

基础地图演示 - 视觉映射器

map.set_global_opts(
 visualmap_opts=VisualMapOpts(
     is_show=True,
     is_piecewise=True,
     pieces=[
         {"min":1,"max":9,"label":"1-9人","clour":"#CCFFFF"},
         {"min":10,"max":99,"label":"10-99人","clour":"#FFFF99"},
         {"min":100,"max":499,"label":"100-499人","clour":"#FF9966"},
         {"min":500,"max":999,"label":"500-999人","clour":"#FF6666"},
         {"min":1000,"max":9999,"label":"1000-9999人","clour":"#CC3333"},
         {"min":10000,"label":"10000以上","clour":"#990033"},
     ]
 )
)

PS:通过ab173网站知到颜色对应代码,网站里的前端按钮,选项卡里有rgb颜色对照表

# 地图可视化基本使用
from pyecharts.charts import Map
from pyecharts.options import VisualMapOpts
# 准备地图对象
map = Map()
# 准备数据
data = [
    ("北京市",99),
    ("上海市",199),
    ("湖南省",299),
    ("台湾省",199),
    ("安徽省",299),
    ("广州省",399),
    ("湖北省",599),
]
# 添加数据
map.add("地图",data,"china")
# 设置全局选项
map.set_global_opts(
    visualmap_opts=VisualMapOpts(
        is_show=True,
        is_piecewise=True,  # 开启手动校准范围
        pieces=[    # 设置范围内容
            {"min":1,"max":9,"label":"1-9人","clour":"#CCFFFF"},
            {"min":10,"max":99,"label":"10-99人","clour":"#FFFF99"},
            {"min":100,"max":499,"label":"100-499人","clour":"#FF9966"},
            {"min":500,"max":999,"label":"500-999人","clour":"#FF6666"},
            {"min":1000,"max":9999,"label":"1000-9999人","clour":"#CC3333"},
            {"min":10000,"label":"10000以上","clour":"#990033"},
        ]
    )
)
# 绘图
map.render()

疫情地图 - 国内疫情地图

# 全国疫情可视化地图开发
from pyecharts.charts import Map
from pyecharts.options import *
import json
# 读取数据文件
f = open("D:/python 代码/可视化案例数据/地图数据/疫情.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"]                   # 省份名称
    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":9,"label":"1-9人","clour":"#CCFFFF"},
            {"min":10,"max":99,"label":"10-99人","clour":"#FFFF99"},
            {"min":100,"max":499,"label":"100-499人","clour":"#FF9966"},
            {"min":500,"max":999,"label":"500-999人","clour":"#FF6666"},
            {"min":1000,"max":9999,"label":"1000-9999人","clour":"#CC3333"},
            {"min":10000,"label":"10000以上","clour":"#990033"},
        ]
    )
)
# 绘图
map.render("全国疫情地图.html")

疫情地图 - 省级疫情地图

# 陕西省疫情可视化地图开发
from pyecharts.charts import Map
from pyecharts.options import *
import json
# 读取数据文件
f = open("D:/python 代码/可视化案例数据/地图数据/疫情.txt","r",encoding="UTF-8")
data = f.read()
# 关闭文件
f.close()
# 获取陕西省数据
# 将字符串json转换为python的字典
data_dict = json.loads(data)
# 取到陕西省城市数据
cities_data = data_dict["areaTree"][0]["children"][15]["children"]
# 准备数据为元组,并放入list
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(("某某市",15))

# 创建地图对象
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":9,"label":"1-9人","clour":"#CCFFFF"},
            {"min":10,"max":99,"label":"10-99人","clour":"#FFFF99"},
            {"min":100,"max":499,"label":"100-499人","clour":"#FF9966"},
            {"min":500,"max":999,"label":"500-999人","clour":"#FF6666"},
            {"min":1000,"max":9999,"label":"1000-9999人","clour":"#CC3333"},
            {"min":10000,"label":"10000以上","clour":"#990033"},
        ]
    )
)
# 绘图
map.render()

第十二章 综合案例-动态柱状图

数据可视化 - 动态柱状图

基础柱状图

通过Bar构建基础柱状图

from pyecharts.charts import Bar
from pyecharts.options import *
# 构建柱状图对象
bar =Bar()

# 添加x轴数据
bar.add_xaxis(["中国","美国","英国"])
# 添加y轴数据
bar.add_yaxis("GDP",[30,20,10])

# 绘图
bar.render("基础柱状图.html")

反转x轴和y轴

# 反转x轴和y轴
bar.reversal_axis()

数值标签在右侧

# 数值标签在右侧
bar.add_yaxis("GDP",[30,20,10],label_opts=LabelOpts(position="right"))
from pyecharts.charts import Bar
from pyecharts.options import *
# 构建柱状图对象
bar =Bar()

# 添加x轴数据
bar.add_xaxis(["中国","美国","英国"])
# 添加y轴数据
# 数值标签在右侧
bar.add_yaxis("GDP",[30,20,10],label_opts=LabelOpts(position="right"))

# 反转x轴和y轴
bar.reversal_axis()

# 绘图
bar.render("基础柱状图.html")

总结

  • 通过Bar()构建一个柱状图对象
  • 和折线图一样,通过add_xaxis()和add_yaxis()添加x轴和y轴数据
  • 通过柱状图对象的:reversal_axis(),反转x轴和y轴
  • 通过label_opts=LabelOpts(position=“right”)设置数值标签在右侧显示

基础时间线柱状图

创建时间线

  • Timeline() - 时间线
    • 通过pyecharts提供的-时间线,描述一个趋势性的数据
    • 如果说一个Bar、Line对象是一张图表的话,时间线就是创建一个一维的x轴,轴上每一个点就是一个图标对象

创建时间线

from pyecharts.charts import Bar,Timeline
from pyecharts.options import *

bar1 = Bar()
bar1.add_xaxis(["中国","美国","英国"])
bar1.add_yaxis("GDP",[30,20,10],label_opts=LabelOpts(position="right"))
bar1.reversal_axis()

bar2 = Bar()
bar2.add_xaxis(["中国","美国","英国"])
bar2.add_yaxis("GDP",[50,30,20],label_opts=LabelOpts(position="right"))
bar2.reversal_axis()

# 创建时间对象
timeline = Timeline()
# timeline对象添加bar柱状图对象
timeline.add(bar1,"2021年GDP")
timeline.add(bar2,"2022年GDP")
# 通过时间线绘制图
timeline.render("基础柱状图-时间线.html")

自动播放

# 自动播放设置
timeline.add_schema(
 play_interval=1000,         # 自动播放的时间间隔,单位毫秒
 is_timeline_show=True,      # 是否在自动播放的时候,显示时间线
 is_auto_play=True,          # 是否自动播放
 is_loop_play=True           # 是否循环自动播放
)

时间线设置主题

from pyecharts.globals import ThemeType
# 创建时间线对象
timeline = Timeline(
 {"theme":ThemeType.LIGHT}
)
# 带有时间线的柱状图开发
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,20,10],label_opts=LabelOpts(position="right"))
bar1.reversal_axis()

bar2 = Bar()
bar2.add_xaxis(["中国","美国","英国"])
bar2.add_yaxis("GDP",[50,30,20],label_opts=LabelOpts(position="right"))
bar2.reversal_axis()

bar3 = Bar()
bar3.add_xaxis(["中国","美国","英国"])
bar3.add_yaxis("GDP",[70,60,60],label_opts=LabelOpts(position="right"))
bar3.reversal_axis()

# 创建时间线对象
timeline = Timeline(
    {"theme":ThemeType.LIGHT}   # 主题设置
)
# timeline对象添加bar柱状图对象
timeline.add(bar1,"2021年GDP")
timeline.add(bar2,"2022年GDP")
timeline.add(bar3,"2023年GDP")
# 自动播放设置
timeline.add_schema(
    play_interval=1000,         # 自动播放的时间间隔,单位毫秒
    is_timeline_show=True,      # 是否在自动播放的时候,显示时间线
    is_auto_play=True,          # 是否自动播放
    is_loop_play=True           # 是否循环自动播放
)

# 通过时间线绘制图
# PS:绘图是用时间线对象绘图,而不是Bar对象了
timeline.render("基础柱状图-时间线.html")

GDP动态柱状图绘制

列表的sort(排序)方法

sorted函数,可以对数据容器进行排序。但是我们需要对列表进行排序,并指定排序规则,sorted函数就无法完成了

补充学习列表的sort方法,使用方式:

  • 列表.sort(key=选择排序依据的函数,reverse=True|False)
    • 参数key,是要求传入一个函数,表示将列表的每一个元素都传入函数中,返回排序的依据
    • 参数reverse,是否反转排序结果,True表示降序,False表示升序

列表的sort方法

  • 带名函数形式

    • # 如下嵌套列表,要求对外层列表进行排序,排序的依据是内层列表的第二个元素数字
      # 以前学习的sorted函数无法适用,可以使用列表的sort方法
      my_list = [["a",33],["b",55],["c",11]]
      # 定义排序方法
      def choose_sort_key(element):
          return element[1]
      # 将元素传入choose_sort_key函数中,用来确定按照谁来排序
      my_list.sort(key=choose_sort_key,reverse=True)
      print(my_list)
      
  • 匿名lambda形式

    • # 如下嵌套列表,要求对外层列表进行排序,排序的依据是内层列表的第二个元素数字
      # 以前学习的sorted函数无法适用,可以使用列表的sort方法
      my_list = [["a",33],["b",55],["c",11]]
      my_list.sort(key=lambda element:element[1],reverse=True)
      print(my_list)
      

动态GDP柱状图需求分析:

  1. GDP数据处理为亿级
  2. 有时间轴,按照年份为时间轴的点
  3. x轴和y轴反转,同时每一年的数据只要前8名国家
  4. 有标题,标题的年份会动态更改
  5. 设置了主题为LIGHT

处理数据:将数据转换为字典存储,格式为:{年份:[[国家,GDP],[国家,GDP],...],年份:[[国家,GDP],[国家,GDP],...],...}

# GDP动态柱状图开发
from pyecharts.charts import Bar,Timeline
from pyecharts.globals import ThemeType
from pyecharts.options import *
import json
# 读取数据
f = open("D:/python 代码/可视化案例数据/动态柱状图数据/1960-2019全球GDP数据.csv","r",encoding="GB2312")
data_lines = f.readlines()    # 读取每一行
# 关闭文件
f.close()
# 删除第一条数据
data_lines.pop(0)
# 数据转换为字典型,格式为:
# 格式为:{年份:[[国家,GDP],[国家,GDP],...],年份:[[国家,GDP],[国家,GDP],...],...}
# 先定义一个字典对象
data_dict = {}
for line in data_lines:
    year = int(line.split(",")[0])  # 年份
    country = line.split(",")[1]    # 国家
    gdp = float(line.split(",")[2]) # gap数据
    # 如何判断字典里面有没有指定的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)
    # 取出本年份前八的国家
    year_data = data_dict[year][0:8]
    x_data = []
    y_data = []
    for country_gdp in year_data:
        x_data.append(country_gdp[0])   # x轴添加国家
        y_data.append(country_gdp[1]/100000000)   # y轴添加GDP数据
    # for循环每一年的数据,基于每一年的数据,创建每一年的bar对象
    bar = Bar()
    x_data.reverse()
    y_data.reverse()
    bar.add_xaxis(x_data)
    bar.add_yaxis("GDP(亿)",y_data,label_opts=LabelOpts(position="right"))
    # 反转x轴和y轴
    bar.reversal_axis()
    # 设置每一年的图表标题
    bar.set_global_opts(title_opts=TitleOpts(title=f"{year}年全球前8的GDP数据"))
    # 在for中,将每一年的bar对象添加到时间线中
    timeline.add(bar,str(year))
# 设置时间线自动播放
timeline.add_schema(
    play_interval=1000,
    is_timeline_show=True,
    is_auto_play=True,
    is_loop_play=False
)
# 绘图
timeline.render("1960-2019年全球GDP前8的国家.html")

博主声明:
本文知识点与代码皆出自黑马程序员课程
欢迎有兴趣的同学进行视频学习
链接:黑马程序员python教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值