Python 基础语法

字面量

定义:在代码中,被写下来的固定的值,称之为字面量

字符串

字符串(String),又称文本,是由任意数量的字符如中文、英文、各类符号、数字等组成,所以叫字符的串。

Python中,字符串需要用双引号包围起来,或者说,被双引号包围起来的,都是字符串。

1
2
3
4
5
6
7
8
666
66.6
"黑马程序员"
# 相比于Java和C,不用在前面写变量类型和后面的分号,如 int = 666; String = “黑马程序yuan”;

print(666)
print(66.6)
print("黑马程序员")

注释

  注:一般多行注释只写在文档开头,其余的用 """''' 定义的都会被识别成普通字符串。

变量

1
2
money = 100
print("钱包还剩:", money, "元") # 钱包还剩: 100 元

  拓展: 在变量中,等号右边可以进行加减乘除等符号运算。

数据类型

如何查看数据类型?

语法:type(被查看类型的数据或变量名)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1.使用print直接输出类型信息
print(type("黑马程序员")) # <class 'str'>
print(type(666)) # <class 'int'>
print(type(10.22)) # <class 'float'>

# 2.使用变量存储type()语句的结果
A = type("黑马程序员")
B = type(666)
C = type(10.22)
print(A) # <class 'str'>
print(B) # <class 'int'>
print(C) # <class 'float'>

# 3.将变量名传入type()语句,再打印输出
name = "黑马程序员"
print(type(name)) # <class 'str'>

  注意:变量本身无类型,但是变量存储的数据是有类型的

类型转换

常见的转换语句

类型转换注意事项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 数字类型转字符串
num_str = str(11)
print(type(num_str), num_str) # <class 'str'> 11
num_float = str(10.22)
print(type(num_float), num_float) # <class 'str'> 10.22

# 字符串转数字类型
str1 = int("11")
print(type(str1), str1) # <class 'int'> 11
str2 = float("10.22")
print(type(str2), str2) # <class 'float'> 10.22

# str3 = int("hhh")
# print(type(str3),str3) # ValueError: invalid literal for int() with base 10: 'hhh'

# 整数转浮点数
f = float(11)
print(type(f), f) # <class 'float'> 11.0

# 浮点数转整数
i = int(10.22)
print(type(i), i) # <class 'int'> 10 高精度转低精度就会精度缺失

标识符

定义:变量名、常量名、函数名、数组名等等,都是为了区分程序中不同的实体、人为起定的名字。通常把这些名字叫做标识符

注意: 不遵守规则会出现问题

​    不遵守规范会不太高级

运算符

字符串扩展

字符串的三种定义方式

1
2
3
4
5
6
7
8
9
10
11
12
name = "黑马程序员"
name = "黑马程序员"
name = """黑马程序员"""

name = "\"黑马程序员\"and\"白马程序员\""
print(name)
name = '\'黑马程序员\''
print(name)
name = "'黑马程序员'" # 单双引号之间就可以不用加转义字符
print(name)

# 注意: 自动格式化插件,如black,会自动帮你转单双引号,避免使用转义字符。

  Python中字符串的单引号和双引号没有什么本质区别,如果想输出单引号,如Let's go!!!,外面就用双引号,否则要用转义字符;如果想输出双引号,如他是个“活雷锋”,外面就用单引号,否则就要有转义字符。

自动格式化

方法一:随时格式化

  • 下载black插件: 在终端输入 pip install black
  • 在设置中配置

  • 测试:name = abc ,在等号前面多输入几个空格,看看是否会自动格式化

    如果能正确运行,在PyCharm下方应该会显示:正在运行 File Watcher ‘代码规范Black’…

  • 如果想要关闭Black插件自动格式化,在设置-工具-File Watcher中,取消勾选即可。

方法二:自动保存时格式化(建议)

  • 下载black插件: 在终端输入 pip install black

  • 在设置中配置

字符串的拼接

方法:用+号连接

1
2
3
4
name = "眯眯"
age = 3
print("我的名字叫" + name + ",我今年" + str(age) + "岁了。")
# 我的名字叫眯眯,我今年3岁了。

缺点: 1. 字符串无法和非字符串变量进行拼接,因为类型不一致,无法接上,需要进行类型转换。

​    2. 如果需要拼接的变量太多,会导致拼起来麻烦,看起来冗长

字符串格式化

1
2
3
4
name = "眯眯"
age = 3
print("我的名字叫%s,我今年%d岁了。" % (name, age)) # 括号里的顺序不要写错了
# 我的名字叫眯眯,我今年3岁了。

1
2
3
PI = 3.14
print("圆周率是%f" % PI) # 精度默认小数点后6位(最后一位四舍五入)
# 圆周率是3.140000

1
2
3
PI = 3.14
print("圆周率是%.2f" % PI) # 限制小数点后的精度为2
# 圆周率是3.14

快速写法

在Python 3.6及以上的版本中,引入了f-string,是一种更简洁更易读的字符串格式化方式。

语法:print(f"{变量}") # 单引号和双引号都可以

1
2
3
4
5
6
name = "祖冲之"
PI = 3.141592653589793
num = 7
# f: format 格式化
print(f"我国杰出数学家{name}算出圆周率的真值约为{PI:.7f},相当于精确到第{num}位。")
# 我国杰出数学家祖冲之算出圆周率的真值约为3.1415927,相当于精确到第7位。

优点: 1. 不用理会数据类型

​    2. 不需要做精度控制

数据输入

1
2
3
4
5
6
7
8
9
10
11
name = input("请你输入你的名字:")
print(f"Wow!{name},你的名字真好听!")

age = input("请你输入你的年龄:")
print(f"输入整数类型,输出的数据类型是{type(age)}")
# 输入整数类型,输出的数据类型是<class 'str'>

# 不管输入什么数据类型,都会被强转为string类型输出,所以我们可以进行强制类型转换
age = int(input("请你输入你的年龄:")) # 进行整数类型强转
print(f"输入整数类型,输出的数据类型是{type(age)}")
# 输入整数类型,输出的数据类型是<class 'int'>

Python 判断语句

布尔类型

  就是说,布尔类型只有两个结果,True or False,我们可以把这个结果存储给一个变量名。

  此外,布尔类型不仅可以自行定义,同时也可以通过计算的来。也就是使用比较运算符进行比较运算得到布尔类型的结果。

1
2
3
4
5
6
7
result = 5 > 2
print(f"判断 5>2 输出的结果是{result},它的数据类型是{type(result)}")
# 判断 1>2 输出的结果是False,它的数据类型是<class 'bool'>

result = "itcast" == "itcat"
print(f"判断两个字符串相等 输出的结果是{result},它的数据类型是{type(result)}")
# 判断两个字符串相等 输出的结果是False,它的数据类型是<class 'bool'>

  这里我们能很明显看出运算符之间也是有优先级的,但也不用可以去记忆,大不了给先运算的加小括号就是了。

运算符优先级(由高到低)

运算符 描述
** 指数
~、+、- 按位翻转、一元加号、一元减号
*、/、%、// 乘、除、取模和取整除
+、- 加法和减法
>>、<< 右移、左移运算符
& 位与运算符
^、| 位异或运算符、位或运算符
<=、<、>、>= 比较运算符
<>、==、!= 等于运算符
=、%=、/=、//=、-=、+=、=、*= 赋值运算符
is、is not 身份运算符
in、not in 成员运算符
and、or、not 逻辑运算符

注: 小括号是绝对的Top级别选手,还在指数上面。

​   按位翻转是指将一个整数的二进制表示中的0变为1,1变为0。

​   一元加号减号就是数字前面的正负号。

​   等于运算符中的 <> 表示不等于,在Python3.0及以后的版本已经不能用了。

   位运算(Bitwise Operations)是计算机处理二进制位(0 和 1)的操作。

​   & 当两个相应的二进制位,都为1,则该位的结果为1,否则为0。

​   ^ 当两个相应的二进制位,相异时,结果为1

​   | 当两个相应的二进制位,有一个为1时,结果位就为1。

比较运算符

if 语句

注: 判断语句的结果,必须是布尔类型 True 或 False

  True会执行if内的代码语句,False则不会执行。

1
2
3
4
5
6
7
age = int(input("请输入你的年龄:"))

if age >= 18: # 冒号不要漏了
print("我成年啦!我可以去网吧通宵啦!")

print(f"我今年已经{age}岁了。")
# 这一条是在if语句之外的,不管输入的值是多少,都会运行。

if else 语句

1
2
3
4
5
6
7
8
9
10
print("欢迎来到融创乐园,本园儿童免费,成人收费!")

age = int(input("请输入您的年龄:"))

if age >= 18:
print("您已成年,需要购票10元。")
else:
print("您未成年,可以免费游玩。")

print("祝您游玩愉快!")

if elif else 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
print("欢迎来到融创乐园!")
day = int(input("请输入今天是周几(1~7):"))
vip_level = int(input("请输入您的VIP等级(1~5):"))
height = int(input("请输入你的身高(cm):"))

if day == 7: # 当我第一条判断满足后,就不会再进行下面的判断了。
print("今天是周日,可以免票。")
elif vip_level > 3 and vip_level <= 5:
print("VIP等级大于3,可以免票。")
elif height < 120:
print("身高小于120cm,可以免票。")
else:
print("不好意思,您需要进行购票,票价为10元/人。")
# else也不是必须要写的,也不是一定要有判断结果的,上面都不满足也无所谓,根据实际情况来。

print("祝您玩得愉快!")

  视频中,判断的顺序并不合理,需要调换一下优先级,下面的代码更能体现。

input输入语句直接写入判断条件中

1
2
3
4
5
6
7
8
9
10
11
print("欢迎来到融创乐园!")
if int(input("请输入今天是周几(1~7):")) == 7:
print("今天是周日,可以免票。")
elif int(input("请输入您的VIP等级(1~5):")) > 3: # 像这一条,我就没法判断是否超出VIP5了
print("VIP等级大于3,可以免票。")
elif int(input("请输入你的身高(cm):")) < 120:
print("身高小于120cm,可以免票。")
else:
print("不好意思,您需要进行购票,票价为10元/人。")

print("祝您玩得愉快!")

  优点:节省代码量,判断成立后就不需要进行多余的输入。

  缺点:弊端如第四行的代码,没法再次进行&的判断,最好还是赋值给一个变量,也不容易出错,也方便修改。

判断语句的嵌套

  嵌套的示例还是不适合用刚刚游乐园的例子,因为游乐园免票有明显的优先级,周日>身高和VIP,现在又限定VIP优先级大于身高,直接按顺序if即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"""
领取礼物标准:
1. 18-30岁的成年人
2. 工龄大于两年,或者职级大于3
"""

# 很明显,第一条的年龄必须达标才要判断第二条工龄和职级,所以需要用到嵌套。

age = int(input("请输入您的年龄:"))
year = int(input("请输入您的工龄:"))
level = int(input("请输入您的职级:"))

if age >= 18 and age <= 30:
if year > 2 or level > 3:
print("恭喜你,可以成功领取礼物!")
else:
print("很抱歉,年龄达标,但是工龄和职级有不达标的,无法领取礼物~")
else:
print("很抱歉,年龄不达标~")

随机数

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

1
2
3
import random

num = random.randint(1, 100) # [a,b] 输入的两个数就是下限和上限,是被包含进去的

Python 循环语句

while循环语句

while循环的注意点

while循环的嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"""
打印输出九九乘法表
"""

i = 1
while i <= 9:
j = 1
while j <= i:
print(
f"{j}*{i}={j*i}", end="\t"
) # 学一下这种写法,表示以''里面的内容结尾,不换行
# print(f'{j}*{i}={j*i}\t',end='') # 这样也行
j += 1
print() # 利用print()换行
i += 1

for循环

for循环注意点

range语句

for循环的变量作用域

1
2
3
for i in range(3):
print(i)
print(i) # 名称 'i' 可能未定义

  在上面这段程序中,i 是初始化在for循环中的,那么他只能作用在for的循环体内
  最后一行也能输出,是因为程序在编译的时候是从上往下编译的,前面定义了 i,且最后被赋值2,
  所以 print(i) 会再次输出2 ,但这是不规范的

1
2
3
4
i = 0
for i in range(3):
print(i)
print(i)

  当 i 初始化在 for 循环外面,那么最后的 print(i) 就不会被警告,能正常规范地输出。

for循环的嵌套

1
2
3
4
5
6
7
8
"""
打印输出九九乘法表
"""

for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}*{i}={j*i}", end="\t")
print()

continue & break

continue

1
2
3
4
for i in "123456":
if i == "4":
continue # 当i是4的时候就结束for循环的当次循环(也就是不会打印4了),开始下次循环,从5开始继续输出
print(i, end="") # 12356

break

1
2
3
4
for i in '123456':
if i == '4':
break # 当i是4的时候就永久结束当前for循环,最终输出123就截止了
print(i, end='') # 123

  注意:在嵌套循环中,continue和break只能作用在所在循环,无法对上层循环起作用。

Python 函数

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

函数的定义

1
2
3
4
5
def say_hi():
print('Hello World!')

say_hi()
say_hi()

函数的参数

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

语法解析

1
2
3
4
5
6
def student_id(i):
print(str(852006) + str(i).zfill(2))
# zfill函数将一个长度为m的字符串,向前补0,直到填充至n个字符 (n>m)

student_id(5)
student_id(19)

注意事项:

  • 函数定义中的参数,称之为形式参数,即形参

  • 函数调用中的参数,称之为实际参数,即实参

  • 函数的参数数量不限,可以是0个,也可以无限,使用逗号分隔开

  • 传入参数的时候,要和形式参数一一对应,逗号隔开

形参与实参

1
2
3
4
5
6
def student(x, y, z):  # x y z是形参
result = x + y + z
print(f"{x} + {y} + {z}的计算结果是:{result}")

student(5, 6, 7) # 5 6 7是实参
# 5 + 6 + 7的计算结果是:18

函数的返回值

语法格式

1
2
3
4
5
6
def add(a, b):
return a + b
# print("结束") # 函数体在遇到return后就结束了,所以写在return后的代码不会执行。

r = add(1, 2)
print(r)

None类型

Python中有一个特殊的字面量:None,其类型是:

无返回值的函数,实际上就是返回了 None 这个字面量,也就是返回了空的意思。

1
2
3
4
5
6
7
8
9
10
def say_hello():
print("Hello World!")
# return None # 有没有这一行没区别

# 使用变量接收say_hello函数的返回值
result = say_hello()
# 打印返回值
print(result)
# 打印返回值类型
print(type(result))

  None 可以主动使用 return 返回,效果等同于不写 return 语句。

函数的说明文档

如何编写

  parameter:参数

如何查看

函数的嵌套调用

变量的作用域

局部变量

全局变量

global 关键字

进阶:函数的多返回值

1
2
3
4
5
6
7
def test_return():
return 1, "hello", True

x, y, z = test_return()
print(x)
print(y)
print(z)

进阶:函数的多种传参方式

位置参数

1
2
3
4
5
def user_info(name, age, gender):
print(f"姓名:{name}, 年龄:{age}, 性别:{gender}")

# 位置参数 - 默认使用形式
user_info("陈平安", 30, "男")

关键字参数

1
2
3
4
5
6
7
def user_info(name, age, gender):
print(f"姓名:{name}, 年龄:{age}, 性别:{gender}")

# 关键字参数
user_info(name="陆芝", age=35, gender="女")
user_info(age=16, gender="男", name="李槐") # 可以不按照参数的定义顺序传参
user_info("赊月", gender="女", age=90)

缺省参数

1
2
3
4
5
6
7
def user_info(name, age=99, gender="沃尔玛购物袋"):
# 一旦某个键设了默认值,那么从这个键往后的键都必须设置默认参数
print(f"姓名:{name}, 年龄:{age}, 性别:{gender}")

user_info("小赵") # 姓名:小赵, 年龄:99, 性别:沃尔玛购物袋
user_info("小钱", 13) # 姓名:小钱, 年龄:13, 性别:沃尔玛购物袋
user_info("小孙", 15, "女") # 姓名:小孙, 年龄:15, 性别:女

不定长参数

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

user_info(1, 2, 3, "小明", "男孩")
# args参数的类型是:<class 'tuple'>,内容是:(1, 2, 3, '小明', '男孩')

  arguments (=args) :参数

1
2
3
4
5
6
# 不定长 - 关键字不定长, **号
def user_info(**kwargs):
print(f"args参数的类型是:{type(kwargs)},内容是:{kwargs}")

user_info(name="小周", age=11, gender="男孩")
# args参数的类型是:<class 'dict'>,内容是:{'name': '小王', 'age': 11, 'gender': '男孩'}

  keyword arguments (=kwargs):关键字参数

进阶:匿名函数

函数作为参数传递

1
2
3
4
5
6
7
8
9
def test_func(compute):
result = compute(1, 2)
print(f"compute参数的类型是:{type(compute)}") # compute参数的类型是:<class 'function'>
print(f"计算结果:{result}") # 计算结果:3

def compute(x, y):
return x + y

test_func(compute)

lambda匿名函数

1
2
3
4
5
6
7
8
def test_func(compute):  # 这个compute是一个形参,下面传入的add是实参,所以名称不一样也没事
result = compute(1, 2)
print(f"结果是:{result}")

def add(x, y):
return x + y

test_func(add) # 结果是:3
1
2
3
4
5
6
def test_func(compute):
result = compute(1, 2)
print(f"结果是:{result}")

# 括号内的即是一次性的compute函数
test_func(lambda x, y: x + y) # 结果是:3

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

Python 数据容器

定义:数据容器是一种可以存储多个元素的python数据类型,它有五类,分别是:list(列表)、tuple(元组)、str(字符串)、set(集合)、dict(字典)

list 列表

列表的定义

1
2
3
4
5
6
7
8
9
# 使用[]的方式定义列表
list = ["python", 888, 10.22] # 里面存储了不同的数据类型
print(list) # ['python', 888, 10.22]
print(type(list)) # <class 'list'>

# 嵌套列表的定义
list = [[1, 2, 3], [4, 5, 6]]
print(list) # [[1, 2, 3], [4, 5, 6]]
print(type(list)) # <class 'list'>

列表的下标(索引)

列表的常用操作(方法)

  方法和函数的区别:(进阶篇的面向对象章节会具体讲,目前只需要知道如何调用即可)

  函数:定义在模块级别,即它们不属于任何类,通过函数名直接调用

  方法:定义在类内部,它们属于类,通过类的实例或类本身调用

总览

编号 使用方式 作用
1 列表.index(元素) 查找指定元素在列表的下标,找不到则报错ValueError
2 列表.insert(下标, 元素) 在指定下标处,插入指定的元素
3 列表.append(元素) 向列表中追加一个元素
4 列表.extend(容器) 将数据容器的内容依次取出,追加到列表尾部
5 del 列表[下标] 删除列表指定下标元素
6 列表.pop(下标) 删除列表指定下标元素
7 列表.remove(元素) 从前向后,删除此元素第一个匹配项
8 列表.clear() 清空列表
9 列表.count(元素) 统计此元素在列表中出现的次数
10 len(列表) 统计列表i内有多少元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
list = ["Python", "Java", "CPP"]
# 1.1 查找某元素在列表内的下标索引
index = list.index("Python")
print(f"Python在列表中的下标索引值是:{index}")

# 1.2如果被查找的元素不存在,会报错
# index = list.index("hello")
# print(f"hello在列表中的下标索引值是:{index}")

# 2. 修改特定下标索引的值
list[0] = "Matlab" # 就是重新赋值
print(f"列表被修改元素值后,结果是:{list}")

# 3. 在指定下标位置插入新元素
list.insert(1, 2024) # 回顾一下,可以插入不同类型元素
print(f"列表插入元素后,结果是:{list}")

# 4. 在列表的尾部追加`单个`新元素
list.append("Ruby")
print(f"列表在追加了元素后,结果是:{list}")
list.append([777, 888, 999]) # 这是将一个列表作为一个元素进行添加,跟第5条进行对比
print(f"列表在追加了元素后,结果是:{list}")

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

# 6. 删除指定下标索引的元素(2种方式)
list = ["a", "b", "c"]
# 6.1 方式1:del 列表[下标]
del list[2]
print(f"列表删除元素后结果是:{list}")

# 6.2 方式2:列表.pop(下标)
list = ["a", "b", "c"]
element = list.pop(2)
print(f"通过pop方法取出元素后列表内容:{list}, 取出的元素是:{element}")

# 7. 删除某元素在列表中的第一个匹配项
list = ["t", "a", "n", "g", "s", "h", "a", "o"]
list.remove("a")
print(f"通过remove方法移除元素后,列表的结果是:{list}")

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

# 9. 统计列表内`某个`元素的数量
list = ["a", "b", "a", "d", "a", "f", "a", "h", "a", "j"]
count = list.count("a")
print(f"列表中a的数量是:{count}")

# 10. 统计列表中`全部`元素的数量
list = ["a", "b", "c", "d", "e", "f", "g", "h", "x", "t"]
count = len(list)
print(f"列表中的元素数量总共有:{count}个")

列表的遍历

既然数据容器可以存储多个元素,那么,就会有需求从容器内依次取出元素进行操作。

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

while循环

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def list_while_func():
"""
使用while循环遍历列表的演示函数
:return: None
"""
my_list = [1, 2, 3, 4, 5]
# 循环控制变量通过下标索引来控制,默认0
# 每一次循环将下标索引变量+1
# 循环条件: 下标索引变量 < 列表的元素数量

# 定义一个变量用来标记列表的下标
index = 0
while index < len(my_list):
element = my_list[index]
print(f"列表的元素: {element}")

# 将循环变量(index) 每一次循环都+1
index += 1


list_while_func()
for循环

语法:

1
2
3
4
5
6
7
8
9
10
11
12
def list_for_func():
"""
使用while循环遍历列表的演示函数
:return: None
"""
my_list = [1, 2, 3, 4, 5]
# for 临时变量 in 数据容器
for element in my_list:
print(f"列表的元素:{element}")


list_for_func()

tuple 元组

不同点

列表可以修改的,元组一旦定义完成,就不可修改,相当于一个只读的列表(list)。

元组的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 定义元组
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的内容是:{t4}")

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

元组的下标(索引)

元组的常用操作(方法)

总览

编号 操作 说明
1 元组.index(元素) 查找指定元素在元组的下标,找不到则报错ValueError
2 元组.count(元素) 统计此元素在元组中出现的次数
3 len(列表) 统计元组内有多少元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# index查找方法
t6 = ("Python", "Java", "CPP")
index = t6.index("Python")
print(f"在元组t6中查找Python的下标是:{index}")

# count统计方法
t7 = ("a", "b", "a", "d", "a", "f", "a", "h", "a", "j")
num = t7.count("a")
print(f"在元组t7中统计a的数量有:{num}个")

# len函数统计元组元素数量
t8 = ("a", "b", "c", "d", "e", "f", "g", "h", "x", "t")
num = len(t8)
print(f"t8元组中的元素有:{num}个")

元组的遍历

注意点

1
2
3
4
5
t9 = (1, 2, ["cat", "dog"])
print(f"t9的内容是:{t9}")
t9[2][0] = "猫"
t9[2][1] = "狗"
print(f"t9的内容是:{t9}")

  注意:元组内的元素不可以修改,但是如果元组内嵌套了列表(list),那么列表内的元素可以进修改。

str 字符串

字符串的定义

字符串的下标(索引)

字符串的常用操作(方法)

总览

编号 操作 说明
1 字符串[下标] 根据下标索引取出特定位置字符
2 字符串.index(字符串) 查找给定字符的第一个匹配项的下标
3 字符串.replace(字符串1, 字符串2) 将字符串内的全部字符串1,替换为字符串2,不会修改原字符串,而是增加一个新的字符串
4 字符串.split(字符串) 按照给定字符串,对字符串进行分隔,不会修改原字符串,而是增加一个新的列表
5 字符串.strip()、字符串.strip(字符串) 移除首尾的空格和换行符或指定字符串
6 字符串.count(字符串) 统计字符串内某字符串的出现次数
7 len(字符串) 统计字符串的字符个数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
str = "cat and dog"
# index方法
value = str.index("and")
print(f"在字符串{str}中查找and,其起始下标是:{value}")

# replace方法
new_str = str.replace("cat", "mimi")
print(f"将字符串{str},进行替换后得到:{new_str}")

# split方法
str = "hello python and mimi"
str_list = str.split(" ")
# 按照指定的分隔符字符串,将字符串划分为多个字符串,并存入列表对象中
# 注意:字符串本身不变,而是得到了一个列表对象
print(f"将字符串{str}进行split切分后得到:{str_list}, 类型是:{type(str_list)}")

# strip方法 规整函数
str = " aa bb cc dd "
new_str = str.strip() # 作用就是去除首尾空格,中间的不变动
print(f"字符串{str}被strip后,结果:{new_str}")

str = "121122cat and dog222121"
new_str = str.strip("12") # 顺序无所谓,个数也无所谓
print(f"字符串{str}被strip('12')后,结果:{new_str}")

str = "11223311"
left_str = str.lstrip("1") # 左规整
print(f"字符串{str}被lstrip('1')后,结果:{left_str}")
str = "11223311"
right_str = str.rstrip("1") # 右规整
print(f"字符串{str}被rstrip('1')后,结果:{right_str}")

# 统计字符串中某字符串的出现次数, count
str = "Shanghai University and Yangzhou University"
count = str.count("University")
print(f"字符串{str}中University出现的次数是:{count}")

# 统计字符串的长度, len()
str = "a & b"
num = len(str) # 空格也是会被统计进去的
print(f"字符串{str}的长度是:{num}")

字符串的遍历

不同点

相比于列表,字符串元素不可以修改的,只能新建字符串,存储的数据类型也只能是字符型

序列的切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 对list进行切片,从1开始,4结束,步长1
list = [0, 1, 2, 3, 4, 5, 6]
result1 = list[1:4] # 步长默认是1,所以可以省略不写
print(f"结果1:{result1}")

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

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

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

# 对列表进行切片,从3开始,到1结束,步长-1
list = [0, 1, 2, 3, 4, 5, 6]
result5 = list[3:1:-1]
print(f"结果5:{result5}")

# 对元组进行切片,从头开始,到尾结束,步长-2
tuple = (0, 1, 2, 3, 4, 5, 6)
result6 = tuple[::-2]
print(f"结果6:{result6}")

set 集合

不同点

列表可修改、支持重复元素且有序

元组、字符串不可修改、支持重复元素且有序

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

集合的定义

集合的常用操作(方法)

总览:

编号 操作 说明
1 集合.add(元素) 集合内添加一个元素
2 集合.remove(元素) 移除集合内指定的元素
3 集合.pop() 从集合中随机取出一个元素
4 集合.clear() 将集合清空
5 集合1.difference(集合2) 得到一个新集合,内含2个集合的差集,原有的2个集合内容不变
6 集合1.difference_update(集合2) 在集合1中,删除集合2中存在的元素,集合1被修改,集合2不变
7 集合1.union(集合2) 得到1个新集合,内含2个集合的全部元素,原有的2个集合内容不变
8 len(集合) 得到一个整数,记录了集合的元素数量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 定义集合
set_empty = set() # 定义空集合
print(f"set_empty的内容是:{set_empty}, 类型是:{type(set_empty)}")

set = {
"Python",
"Java",
"CPP",
"Python",
"Java",
"CPP",
"Python",
"Java",
"CPP",
}
print(f"set的内容是:{set}, 类型是:{type(set)}")

# 添加新元素
set.add(1022)
set.add(1022) # 不管添加几个,都会默认去重
print(f"set添加元素后结果是:{set}")

# 移除元素
set.remove("CPP")
print(f"set移除CPP后,结果是:{set}")

# 随机取出一个元素
set = {"Python", "Java", "CPP"}
element = set.pop()
print(f"集合被取出元素是:{element}, 取出元素后:{set}")

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

# 取2个集合的差集
set1 = {1, 2, 3}
set2 = {1, 5, 6}
set3 = set1.difference(set2) # 在set1中找出set2中没有的元素,传给set3
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"消除差集后,集合1结果:{set1}")
print(f"消除差集后,集合2结果:{set2}")

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

# 统计集合元素数量len()
set1 = {1, 2, 3, 4, 5, 1, 2, 3, 4, 5}
num = len(set1)
print(f"集合内的元素数量有:{num}个")

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

dict 字典

字典的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 定义字典
dict1 = {"枫原万叶": 99, "神里绫华": 88, "达达利亚": 77}
# 定义空字典
dict2 = {} # 方式1
dict3 = dict() # 方式2
print(f"字典1的内容是:{dict1}, 类型:{type(dict1)}")
print(f"字典2的内容是:{dict2}, 类型:{type(dict2)}")
print(f"字典3的内容是:{dict3}, 类型:{type(dict3)}")

# 定义重复Key的字典
dict1 = {
"枫原万叶": 99,
"枫原万叶": 88,
"达达利亚": 77,
} # 有相同的key,只会保留后一个value
print(f"重复key的字典的内容是:{dict1}")

# 从字典中基于Key获取Value
dict1 = {"枫原万叶": 99, "神里绫华": 88, "达达利亚": 77}
score = dict1["枫原万叶"]
print(f"枫原万叶的考试分数是:{score}")
score = dict1["神里绫华"]
print(f"神里绫华的考试分数是:{score}")

# 定义嵌套字典
stu_score_dict = {
"枫原万叶": {"剑术": 77, "飞行": 66, "历史": 33},
"神里绫华": {"剑术": 88, "飞行": 86, "历史": 55},
"达达利亚": {"剑术": 99, "飞行": 96, "历史": 66},
}
print(f"学生的考试信息是:{stu_score_dict}")

# 从嵌套字典中获取数据
score = stu_score_dict["神里绫华"]["剑术"]
print(f"神里绫华的剑术分数是:{score}")
score = stu_score_dict["达达利亚"]["历史"]
print(f"达达利亚的历史分数是:{score}")

字典的常用操作(方法)

总览

编号 操作 说明
1 字典[Key] 获取指定Key对应的Value值
2 字典[Key] = Value 添加或更新键值对
3 字典.pop(Key) 取出Key对应的Value并在字典内删除此Key的键值对
4 字典.clear() 清空字典
5 字典.keys() 获取字典的全部Key,可用于for循环遍历字典
6 len(字典) 计算字典内的元素数量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
dict = {"陈平安": 99, "齐静春": 88, "刘羡阳": 77}
# 新增元素
dict["顾璨"] = 66
print(f"字典经过新增元素后,结果:{dict}")

# 更新元素
dict["陈平安"] = 80
print(f"字典经过更新元素后,结果:{dict}")

# 删除元素
score = dict.pop("陈平安") # 通过key作为索引删掉键值对key:value
print(f"字典中被移除了一个元素,结果:{dict}, 陈平安的拳法得分是:{score}")

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

# 获取全部的key
dict = {"陈平安": 99, "齐静春": 88, "刘羡阳": 77}
keys = dict.keys()
print(f"字典的全部keys是:{keys}")
print("-----------------------")

# 遍历字典
# 方式1:通过获取到全部的key来完成遍历
for key in keys:
print(f"字典的key是:{key}")
print(f"字典的value是:{dict[key]}")
print("-----------------------")

# 方式2:直接对字典进行for循环,每一次循环都是直接得到key
for key in dict:
print(f"字典的key是:{key}")
print(f"字典的value是:{dict[key]}")
print("-----------------------")

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

5类数据容器对比

数据容器的通用操作

总览

编号 功能 描述
1 通用for循环 遍历容器(字典是遍历key)
2 len() 容器元素个数
3 max 容器内最大元素
4 min() 容器内最小元素
5 list() 转换为列表
6 str() 转换为字符串
7 tuple() 转换为元组
8 set() 转换为集合
9 sorted(序列, [reverse=True]) 排序,reverse=True表示降序,得到一个排好序的列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
list = [3, 1, 2, 5, 4]
tuple = (3, 1, 2, 5, 4)
str = "bdcefga"
set = {3, 1, 2, 5, 4}
dict = {"key3": 1, "key1": 2, "key2": 3, "key5": 4, "key4": 5}

print(f"列表对象的排序结果:{sorted(list)}")
print(f"元组对象的排序结果:{sorted(tuple)}")
print(f"字符串对象的排序结果:{sorted(str)}")
print(f"集合对象的排序结果:{sorted(set)}")
print(f"字典对象的排序结果:{sorted(dict)}")

print(f"列表对象的反向排序结果:{sorted(list, reverse=True)}")
print(f"元组对象的反向排序结果:{sorted(tuple, reverse=True)}")
print(f"字符串对象反向的排序结果:{sorted(str, reverse=True)}")
print(f"集合对象的反向排序结果:{sorted(set, reverse=True)}")
print(f"字典对象的反向排序结果:{sorted(dict, reverse=True)}")

list1 = [3, 1, 2, 5, 4]
list1.sort()
print(list1)
"""
普通的升序排序调用sorted()函数,会返回新的有序列表;
如果用list.sort()方法,它会原地修改原列表(并返回 None 以避免混淆)。
往往不如sorted()方便,但如果不需要原列表,用它会稍微高效一些
另一个区别是list.sort()方法只为列表定义,而sorted()函数接受任何可迭代对象。
"""

  在‌python中,字符串比较基于‌字典序(lexicographical order),即字符编码(如‌ASCII或‌Unicode)的比较

  比较从第一个字符开始,逐个字符进行比较,直到找到不同的字符或到达字符串的末尾

  例如,”apple“ 小于 “banana”,因为 “a“ 的ASCII值小于 “b“。

  ”abc000“ 小于 “abd“,因为 “c“ 的ASCII值小于 “d“,一旦有了大小差异,便不再往后继续比较了。

Python 文件操作

打开文件

  如图可知,open() 函数内置8个参数,encoding在第4位,不能直接用位置参数来传参。

mode常用模式 描述
r (read) 只读方式打开文件,文件的指针将会放在文件的开头,这是默认模式。
w (write) 打开一个文件只用于写入,如果该文件已存在则打开文件,并从开头开始编辑原有内容会被删除
如果该文件不存在,创建新文件谨慎使用 w 模式
a (append) 打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后
如果该文件不存在,创建新文件进行写入。
1
2
3
4
5
6
7
8
9
# f = open("D:\Desktop\abc.txt", "r", encoding="UTF-8")
# 反斜杠(\),会被默认识别成转义字符,解决方式有3种

f1 = open(r"D:\Desktop\abc.txt", "r", encoding="UTF-8") # 在字符串前加上字母r,将其标记为原始字符串
f2 = open("D:\\Desktop\\abc.txt", "r", encoding="UTF-8") # 转义一下反斜杠
f3 = open("D:/Desktop/abc.txt", "r", encoding="UTF-8") # 使用正斜杠
print(type(f1)) # <class '_io.TextIOWrapper'> 即对文本文件进行IO操作的一个类
print(type(f2))
print(type(f3))

读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
f = open(r"D:\Desktop\abc.txt", "r", encoding="UTF-8")
# read()
print(f"读取10个字节的结果:{f.read(10)}") # 可以注意到,换行符\n是会作为1个字节保留的
"""
读取10个字节的结果:hello
worl
"""
print(f"read方法读取全部内容的结果是:{f.read()}")
"""
read方法读取全部内容的结果是:d
Python
Java
1022
"""
# 到目前为止,abc.txt文件中的内容已经全部输出了,其指针已经从开头逐步跳到了末尾
print("-----------------------------------------------")

# readLines()
lines = f.readlines() # 读取文件的全部行,封装到列表中
print(f"lines对象的类型:{type(lines)}")
print(f"lines对象的内容是:{lines}") # 因为上面指针已经在文末了,所以找不到可读内容了,故而输出空列表
f.close() # 结束了就要关闭文件,养成良好习惯,如果不关闭文件就会一直占用

f = open(r"D:\Desktop\abc.txt", "r", encoding="UTF-8") # 重新打开,指针又在开头了
print(f"逐行输出对象的结果是:{f.readlines()}")
# 逐行输出对象的结果是:['hello\n', 'world\n', 'Python\n', 'Java\n', '1022']
f.close()

f = open(r"D:\Desktop\abc.txt", "r", encoding="UTF-8")
# readline()
line1 = f.readline()
line2 = f.readline()
line3 = f.readline()
print(f"第一行数据是:{line1}")
print(f"第二行数据是:{line2}")
print(f"第三行数据是:{line3}")
f.close()

f = open(r"D:\Desktop\abc.txt", "r", encoding="UTF-8")
# for循环读取文件行
for line in f: # line就是一个变量名,换成i也行
print(f"每一行数据是:{line}")
f.close()

1
2
3
4
# with open 语法操作文件
with open(r"D:\Desktop\abc.txt", "r", encoding="UTF-8") as f:
for line in f:
print(f"每一行数据是:{line}")

操作汇总

操作 功能
文件对象 = open(file, mode, encoding) 打开文件获得文件对象
文件对象.read(num) 读取指定长度字节,若不指定num,则会读取文件全部内容
文件对象.readline() 读取一行
文件对象.readlines() 读取全部行,得到列表
for line in 文件对象 for循环文件行,一次循环得到一行数据
文件对象.close() 关闭文件对象
with open() as f 通过with open语法打开文件,可以自动关闭

写入文件

1
2
3
4
5
6
7
8
f = open("python.txt", "w", encoding="utf-8")

f.write("Hello Python!")

f.flush() # 这个操作其实是强制写入,更保险一点
# 官方说法:将缓冲区中的数据立即写入到目标设备中,而不是等到缓冲区满了才进行写入。

f.close() # close()方法其实内置了flush的功能的

注意:

  • w 模式,文件不存在,会创建新文件

  • w 模式,文件存在,会清空原有内容

  • close() 方法,带有 flush() 方法的功能

追加文件

1
2
3
4
5
f = open("python.txt", "a", encoding="UTF-8")

f.write("\nYou're a fake fan,I am Java!") # 跟w模式进行对比,不会清空原有内容,所以w模式一定要慎用!!!

f.close()

注意:

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

  • a 模式,文件存在,会在原有内容后面继续写入

  • 可以使用 \n 来写出换行符

Python 异常、模块与包

异常

异常的定义

异常的捕获

1
2
3
4
try:
f = open("linux.txt", "r")
except:
f = open("linux.txt", "w")

1
2
3
4
5
6
7
try:
name # name未定义内容,上述演示中,print(name)自然也是报相同的错误
# 1 / 0 # ZeroDivisionError: division by zero 显然这个异常不叫NameError,所以无法捕获
except NameError as e: # as e 就是用e这个变量,来接收这个异常
print("name变量名称未定义错误")
# 输出e所接收的内容
print(e) # name 'name' is not defined

1
2
3
4
5
6
7
8
try:
print(1 / 0) # 当出现异常后,后面的内容就不再输出,直接跳转到except
print(name)
except (NameError, ZeroDivisionError) as e:
print("出现了变量未定义 或者 除以0的异常错误")
# 通过对e的输出,也可以看出,只捕获了第一条异常
print(e) # division by zero
# 如果没有正确设置捕获异常类型,就会无法捕获异常

1
2
3
4
5
6
7
8
9
10
try:
f = open("123.txt", "r", encoding="UTF-8")
except Exception as e:
print("出现异常了~")
f = open("123.txt", "w", encoding="UTF-8")
else: # 可写可不写
print("哈哈没有异常!")
finally: # 可写可不写
print("我是finally,有没有异常都需要执行!")
f.close()

  注意:

  我们可以注意到except: 和 except Exception: 都可以捕获所有异常,但还是有所区别的,其中except可捕获所有异常,包括BaseException、SystemExit等,但使用需谨慎。except Exception用于处理普通异常,不包括BaseException等特殊异常,且except Exception后面可以接as e。

  在编写代码时,推荐尽量捕获特定的异常,以提高代码的可读性和稳定性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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()函数,main函数里面调用func2(),func2()函数里面调用func1().
main()
'''
利用异常具有传递性的特点, 当我们想要保证程序不会因为异常而崩溃的时候,
就可以在main()函数中设置异常捕获, 由于无论在整个程序哪里发生异常,
最终都会传递到main()函数中, 这样就可以确保所有的异常都会被捕获。
'''

模块

模块的导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 使用import导入time模块,使用sleep功能(函数)
import time # 导入Python内置的time模块(time.py这个代码文件)

print("你好")
time.sleep(5) # 通过 模块名.xxx() 就可以使用模块内部的全部功能(类、函数、变量)
print("我好")

# 使用from导入time的sleep功能(函数)
from time import sleep

print("你好")
sleep(5)
print("我好")

# 使用 * 导入time模块的全部功能
from time import * # *表示全部的意思

print("你好")
sleep(5)
print("我好")

# 使用as给特定功能加上别名,一般比较长的才需要加别名
import time as t

print("你好")
t.sleep(5)
print("我好")

from time import sleep as sl

print("你好")
sl(5)
print("我好")

注意:

  • import 模块:导入一个模块;注:相当于导入的是一个文件夹,是个相对路径。

  • from… import:导入了一个模块中的一个函数;注:相当于导入的是一个文件夹中的文件,是个绝对路径。

    所以使用上的的区别是,当引用文件时:

    1
    2
    3
    import   //模块名.功能名

    fromimport // 直接使用函数名使用就可以了

自定义模块

1
2
3
# my_module1.py
def test(a, b):
print(f"{a}+{b}={a+b}")
1
2
3
# my_module2.py
def test(a, b):
print(f"{a}-{b}={a-b}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 导入自定义模块使用
# 方式1
import my_module1 # 注意:函数在引用的时候,就会自动执行一遍

my_module1.test(1, 2)

# 方式2
from my_module1 import test

test(1, 2)

# 导入不同模块的同名功能
from my_module1 import test # 变灰表示没有被调用
from my_module2 import test

test(1, 2)

1
2
3
4
5
# my_module.py
def test(a, b):
print(f"{a}+{b}={a+b}")

test(0, 1)
1
2
import my_module  # 0+1=1
# 这仅仅引入了my_module模块并没有其他操作,显然,在运行后却能输出模块中的内容

  详解:

  __name__是一个内置变量,用于表示当前模块的名字。

  在Python底层设置中,当一个Python文件被直接运行时,它的__name__值为__main__,我们可以通过print(__name__)查看。

  当该文件被导入到其他文件中时,它的__name__值则为该文件的名称

  这个变量可以用来区分一个文件是被直接运行还是被导入到其他文件中。

  所以上述 if 语句表示,只有当__name__的值是_main\_时,才打印输出测试语句。

自定义包

1
2
3
# my_package.my_module1
def info_print1():
print("我是模块1")
1
2
3
# my_package.my_module2
def info_print2():
print("我是模块2")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 导入自定义的包中的模块,并使用
# 方式1
import my_package.my_module1 # 像这种长不拉几的,就建议as一个别名
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()

第三方包

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