参考文章:算法乐园的Python笔记

基本概念

print函数

基本用法

最简单的用法就是直接打印一个字符串:

1
print("Hello, World!")

这将在控制台上输出:

1
Hello, World!

打印多个值

你也可以在一次print调用中打印多个值,只需用逗号隔开它们:

1
print("Hello,", "World!")

输出:

1
Hello, World!

打印变量

当然,print函数也可以用于打印变量的值:

1
2
3
x = 10
y = 20
print("x =", x, ", y =", y)

输出:

1
x = 10 , y = 20

换行与分隔符

默认情况下,print函数会在每个值之间添加一个空格,并在最后添加一个换行符。你可以通过sepend参数来自定义这些行为:

1
print("Hello", "World", sep="-", end="!!!\n")

输出:

1
Hello-World!!!

格式化字符串的语法

格式化字符串使用fF前缀来标识,后面跟着一个字符串字面量,其中可以包含花括号{}内的表达式。这些花括号内的表达式将在运行时被计算,并用其结果替换花括号。

基本用法

1
2
3
4
name = "Alice"  
age = 30
greeting = f"Hello, my name is {name} and I am {age} years old."
print(greeting) # 输出: Hello, my name is Alice and I am 30 years old.

在上面的例子中,变量nameage被插入到了字符串中的相应位置。

input语句

基本用法

input()函数的基本用法非常简单。当调用它时,程序会暂停并等待用户输入。用户可以在命令行或交互式环境中输入文本,然后按Enter键提交输入。

下面是一个简单的例子:

1
2
user_input = input("请输入一些文本:")  
print("你输入的是:", user_input)

在这个例子中,程序首先打印出提示信息”请输入一些文本:”,然后等待用户输入。用户输入的内容将被赋值给变量user_input,然后程序打印出”你输入的是:”后面跟着用户输入的内容。

输入类型

需要注意的是,input()函数返回的总是一个字符串类型。即使你输入的是一个数字,它也会被当作字符串处理。如果你需要将输入转换为其他类型(如整数或浮点数),你需要使用相应的类型转换函数。

注释

单行注释

Python 中的单行注释以 # 开头。# 符号后面的所有内容都会被视为注释,直到该行的结束。

1
2
# 这是一个单行注释  
x = 5 # 可以在代码行的末尾添加注释

多行注释

Python 本身并没有直接支持多行注释的语法,但我们可以使用三重引号("""''')来实现类似的效果。三重引号通常用于多行字符串,但如果没有将它们赋值给变量或用作其他目的,它们也可以用作多行注释。

1
2
3
4
5
6
7
8
9
10
11
12
"""  
这是一个多行注释的
示例。你可以在这里写下
多行文字来描述你的代码。
"""

# 或者使用三个单引号
'''
这也是一个多行注释的示例,
和上面的三重双引号具有相同的效果。
选择哪种风格通常取决于个人或团队的偏好。
'''

语句

Python 中一般以新行作为语句的结束标识,可以使用 \ 将一行语句分为多行显示。如下所示:

1
2
3
4
5
6
a = 128
b = 1024
c = 512
d = a + \
b - \
c

如果包含在 []、{}、() 括号中,则不需要使用 \。如下所示:

1
2
3
4
5
arr = {
a,
b,
c
}

Python变量及基本数据

类型介绍

在Python编程语言中,数据类型是一个重要的概念,它决定了变量可以保存何种类型的数据以及可以对这些变量执行哪些操作。Python有几种基本(或内置)的数据类型,包括整数(int)、浮点数(float)、字符串(str)等,但请注意字符(char)这一概念在Python中并不作为一个独立的基本数据类型存在,字符通常被视为长度为1的字符串。

1. 整数(Integers)

整数是没有小数部分的数字,可以是正数或负数。在Python中,整数的大小只受限于可用内存。

1
2
x = 10   # 定义一个整数
y = -20 # 定义一个负整数

Python 3中的整数是动态大小的,意味着Python整数可以处理任意大小的整数,只要内存允许。

2. 浮点数(Floating Point Numbers)

浮点数是有小数点的数字,它们用于表示实数。

1
2
x = 1.23   # 定义一个浮点数
y = -4.56 # 定义一个负的浮点数

浮点数在计算机中的表示是近似的,因此在进行浮点数运算时要特别注意精度问题。

3. 字符串(Strings)

字符串是由零个或多个字符组成的有序字符序列。在Python中,字符串是不可变的。

1
2
s1 = "Hello"  # 定义一个字符串
s2 = 'World' # 字符串也可以用单引号定义

字符串可以通过连接(concatenation)形成新的字符串,也可以用切片(slicing)来访问子字符串。

4. 字符(Characters)

在Python中,并没有专门的“字符”数据类型。相反,字符被视为长度为1的字符串。你可以通过索引字符串来获取单个字符。

1
2
s = "Hello"
char = s[0] # 获取字符串中的第一个字符,结果为 'H'

在这个例子中,char 实际上是一个长度为1的字符串,它包含了字符 ‘H’。在Python中处理单个字符时,你通常会使用长度为1的字符串。

变量

1
2
3
4
5
6
# 定义一个变量money,并赋值为10
money = 10
# 对money变量进行减法操作,减去5
money = money - 5
# 打印money变量的值
print("余额为", money, "元")

查看数据类型

可以使用type()函数来查看一个变量的数据类型。

1
2
3
4
5
6
# 定义几个变量,并分别赋予不同的数据类型
string_type = "hello world"
int_type = 666
float_type = 114.514
# 使用type()函数查看变量的数据类型
print(type(string_type), type(int_type), type(float_type))

运行这段代码,你会得到输出<class 'str'> <class 'int'> <class 'float'>,说明这三个变量的数据类型分别是字符串、整数和浮点数。

数据类型转换

在Python中,你可以使用内置的函数来进行数据类型之间的转换。常见的转换函数有int()float()str()

  • int(x):将x转换为一个整数。如果x是一个浮点数,会舍去小数部分。如果x是一个字符串,且字符串内容可以转换为整数,则会转换为相应的整数;否则会报错
  • float(x):将x转换为一个浮点数。如果x是一个整数,会在其后面添加.0。如果x是一个字符串,且字符串内容可以转换为浮点数,则会转换为相应的浮点数;否则会报错
  • str(x):将x转换为一个字符串。无论x是什么数据类型,都会转换为其对应的字符串形式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 将浮点数转换为字符串
float_str = str(114.514)
print(type(float_str), float_str)

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

# 将字符串转换为浮点数
num2 = float("1919.810")
print(type(num2), num2)

# 将整数转换为浮点数
fnum = float(11)
print(type(fnum), fnum)

# 将浮点数转换为整数,注意这里不会四舍五入,而是直接舍去小数部分
inum = int(114.514)
print(type(inum), inum)

运行这段代码,你会得到以下输出:

1
2
3
4
5
<class 'str'> 114.514
<class 'int'> 11
<class 'float'> 1919.81
<class 'float'> 11.0
<class 'int'> 114

注意在进行数据类型转换时,要确保转换是合法的,否则程序会报错。例如,尝试将一个包含非数字字符的字符串转换为整数或浮点数会导致ValueError

标识符

标识符命名只允许出现:(和C++一样)

  • 英文字母
  • 中文(不推荐)
  • 数字(不可以开头)
  • 下划线_

处理数据类型

Python的运算符介绍

1. 算术运算符

算术运算符用于执行基本的数学运算。

  • +:加法运算符,用于计算两个数的和。
  • -:减法运算符,用于计算两个数的差。
  • *:乘法运算符,用于计算两个数的积。
  • /:除法运算符,用于计算两个数的商。(python两个整数相除会得到浮点数)
  • //:整除运算符,用于计算两个数整除后的结果(只保留整数部分)。整除取整方向默认为$−∞$。
  • %:取模运算符,用于计算两个数相除后的余数。
  • **:幂运算符,用于计算一个数的幂。

2. 比较运算符

比较运算符用于比较两个值的大小关系,返回一个布尔值(True或False)。

  • ==:等于运算符,用于判断两个值是否相等。
  • !=:不等于运算符,用于判断两个值是否不相等。
  • >:大于运算符,用于判断左侧的值是否大于右侧的值。
  • <:小于运算符,用于判断左侧的值是否小于右侧的值。
  • >=:大于等于运算符,用于判断左侧的值是否大于或等于右侧的值。
  • <=:小于等于运算符,用于判断左侧的值是否小于或等于右侧的值。

3. 逻辑运算符

逻辑运算符用于组合多个条件表达式,返回一个布尔值。

  • and:逻辑与运算符,当所有条件都为True时,返回True。

  • or:逻辑或运算符,当至少有一个条件为True时,返回True。

  • not:逻辑非运算符,用于取反一个布尔值。

    Python中的逻辑判断:与、或、非

    在Python中,逻辑运算符用于连接布尔表达式,并根据这些表达式的真假值返回结果。与Java等其他语言相比,Python的逻辑运算符有一些独特之处,特别是在处理非布尔类型的值时。

    逻辑运算符

    Python中的逻辑运算符包括:

    • and:逻辑与
    • or:逻辑或
    • not:逻辑非
    逻辑运算符的行为
    逻辑与 (and)

    当使用and运算符时:

    • 如果所有表达式的值都为真(非零、非空等),则返回最后一个表达式的值。
    • 如果有一个或多个表达式的值为假(零、空等),则返回第一个假值。
    逻辑或 (or)

    当使用or运算符时:

    • 如果有一个或多个表达式的值为真,则返回第一个真值。
    • 如果所有表达式的值都为假,则返回最后一个假值。
    逻辑非 (not)

    not运算符返回表达式的布尔否定值。如果表达式为真,则返回False;如果表达式为假,则返回True

    示例

    下面是一些Python逻辑运算符的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 逻辑与 (and)
    print(3 > 2 and 3 > 1) # True,因为两个条件都为真
    print(3 and 2) # 2,因为3为真,返回第二个值2
    print(0 and None) # 0,因为0为假,返回第一个假值0

    # 逻辑或 (or)
    print(3 > 2 or 3 > 1) # True,因为至少有一个条件为真
    print(2 or 3 > 2) # 2,因为2为真,返回第一个真值2
    print(0 or None) # None,因为两者都为假,返回最后一个假值None

    # 逻辑非 (not)
    print(not 3) # False,因为3为真值
    print(not 0) # True,因为0为假值

    为假的值

    在Python中,以下值在布尔上下文中被视为False

    • 数值类型中的00.0
    • 空序列类型,如空字符串''、空列表[]、空元组()、空字典{}
    • None对象
    • 布尔类型本身的False

    需要注意的是,当这些“假值”作为逻辑表达式的一部分时,它们本身会被返回作为结果,而不是布尔值False。这是Python逻辑运算符与其他语言(如Java)的一个主要区别。在Java中,逻辑运算符只能用于布尔表达式,并且结果总是布尔值。而在Python中,逻辑运算符可以更加灵活地用于不同类型的值,并返回这些值本身作为结果。这种特性使得Python代码在某些情况下可以更加简洁和高效。但同时也需要注意逻辑运算符的这种行为可能会带来的潜在混淆和错误。因此在使用时需要特别小心并确保理解其行为规则。

4. 位运算符

位运算符用于对二进制位进行操作。

  • &:按位与运算符,对两个数的二进制位进行与操作。
  • |:按位或运算符,对两个数的二进制位进行或操作。
  • ^:按位异或运算符,对两个数的二进制位进行异或操作。
  • ~:按位取反运算符,对一个数的二进制位进行取反操作。
  • <<:左移运算符,将一个数的二进制位向左移动指定的位数。
  • >>:右移运算符,将一个数的二进制位向右移动指定的位数。

5. 赋值运算符

赋值运算符用于将表达式的值赋给变量。

  • =:赋值运算符,将右侧表达式的值赋给左侧的变量。
  • +=:加法赋值运算符,将右侧的值加到左侧的变量上,并将结果赋给左侧的变量。
  • -=:减法赋值运算符,将右侧的值从左侧的变量中减去,并将结果赋给左侧的变量。
  • *=:乘法赋值运算符,将右侧的值与左侧的变量相乘,并将结果赋给左侧的变量。
  • /=:除法赋值运算符,将左侧的变量除以右侧的值,并将结果赋给左侧的变量。
  • %=:取模赋值运算符,将左侧变量与右侧值进行取模运算,并将结果赋给左侧的变量。
  • **=:幂赋值运算符,将左侧变量进行幂运算后的结果赋给左侧的变量。
  • //=:整除赋值运算符,将左侧变量与右侧值进行整除运算后的结果赋给左侧的变量。

6. 身份运算符

身份运算符用于比较两个对象的身份是否相同。

  • is:判断两个标识符是否引用同一个对象。
  • is not:判断两个标识符是否引用不同的对象。

7. 成员运算符

成员运算符用于判断一个值是否存在于序列中(如列表、元组、字符串等)。

  • in:如果指定的值在序列中找到,则返回True,否则返回False。
  • not in:如果指定的值没有在序列中找到,则返回True,否则返回False。

这些运算符在Python编程中非常常用,掌握它们对于编写高效的Python代码至关重要。

字符串操作

字符串拼接

在Python中,你可以使用加号(+)操作符来拼接(连接)两个或多个字符串。

1
2
3
4
s1 = "abcd"
s2 = "defg"
s3 = s1 + s2
print(s3) # 输出:abcddefg

字符串格式化

Python 提供了多种方式来格式化字符串,其中 % 操作符是一种较旧的方法,但在某些情况下仍然很有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用%s作为字符串占位符,%d作为整数占位符,%f作为浮点数占位符
num = 114514
s = "abcde"
message1 = "%s你好世界" % s
print(message1) # 输出:abcde你好世界

message2 = "%s你好世界%d" % (s, num)
print(message2) # 输出:abcde你好世界114514

# 另一个例子,包含浮点数
s = "绩点"
gpa = 0.1
num = 666
message = "%s高达%.1f,老铁%d" % (s, gpa, num)
print(message) # 输出:绩点高达0.1,老铁666

注意:%.1f 表示浮点数将被格式化为小数点后保留一位。

字符串格式化的一种快速写法

格式:f”内容{变量}”(不关心精度控制)

1
2
3
4
5
s = "绩点"
gpa = 0.1
num = 666
message = f"{s}高达{gpa},大佬{num}"
print(message)

字符转ASCII和ASCII转字符串

在Python中,你可以使用 ord() 函数将一个字符转换成其对应的ASCII数值,使用 chr() 函数将一个ASCII数值转换成对应的字符。

1
2
print(ord("a"))  # 输出:97
print(chr(97)) # 输出:a

字符串的大小写转化

Python 提供了几种方法来改变字符串的大小写。

1
2
3
4
5
6
7
8
9
10
11
# 使用 title() 方法将字符串中每个单词的首字母变成大写,其余小写
str = "wHat a beaUTIFul GIrl!!"
print(str.title()) # 输出:What A Beautiful Girl!!

# 使用 upper() 方法将字符串中所有字母变成大写
str = "Cpp Is The Best Programing Language"
print(str.upper()) # 输出:CPP IS THE BEST PROGRAMING LANGUAGE

# 使用 lower() 方法将字符串中所有字母变成小写
str = "I HATE PYTHOn"
print(str.lower()) # 输出:i hate python

注意:这些方法都不会改变原始字符串,而是返回一个新的字符串。因为Python中的字符串是不可变的。

浮点数精度控制

使用%格式化浮点数

下面是一些使用%运算符和.yf格式来格式化浮点数的例子:

1
2
3
4
5
6
7
8
9
10
11
# 定义一个浮点数  
number = 3.141592653589793

# 使用%格式化方法,保留两位小数
formatted_number = "%.2f" % number
print(formatted_number) # 输出: 3.14

# 如果需要指定总宽度(包括小数点和小数),则使用x.yf格式
# 但这里的总宽度仅包括小数点前的数字、小数点和小数点后的数字,不包括可能的负号或指数部分
formatted_number_with_width = "%8.2f" % number
print(formatted_number_with_width) # 输出: " 3.14"(前面有空格填充以达到总宽度8)

条件与循环

1. 条件语句

1.1 布尔类型

布尔类型(bool)用于表示逻辑值,其中 True 表示真(逻辑上的1),False 表示假(逻辑上的0)。

1.2 条件表达式

条件表达式的结果是布尔类型。例如,比较运算符(如 ><== 等)的结果就是布尔类型。

1
2
3
num1 = 11
num2 = 20
print(f"11 > 20 的结果是 {11 > 20}, 类型为 {type(11 > 20)}") # 输出 False 和 <class 'bool'>

1.3 if-elif-else 语句

if-elif-else 语句用于根据条件执行不同的代码块。

1
2
3
4
5
6
7
num = int(input("请输入一个数字:"))
if num < 10:
print(f"{num} < 10")
elif num <= 100:
print(f"{num} <= 100")
else:
print(num)

在这个例子中,根据输入的数字大小,程序会输出不同的结果。注意要写$:$

1.4 pass 语句

pass 是一个空语句,它不做任何事情。它通常用作占位符,以保持程序结构的完整性。

1
2
3
4
5
num = int(input("请输入一个数字:"))
if num <= 100:
pass # 这里什么也不做
else:
print(num) # 只有当 num > 100 时才会执行这条语句

2. 循环语句

2.1 while 循环

while 循环会重复执行一段代码,直到条件不再满足为止。

1
2
3
4
5
6
x = 1
add = 0
while x <= 100:
add += x # 累加 x 的值到 add 变量中
x += 1 # x 自增 1
print(add) # 输出累加结果,从 1 加到 100 的和为 5050

2.2 for 循环

for 循环用于遍历序列类型(如字符串、列表、元组等)中的元素。

1
2
3
4
5
6
7
s = "abcdef"
for ch in s: # 遍历字符串 s 中的每个字符
if ch == "a":
continue # 跳过当前循环的剩余部分,进入下一次循环
if ch == "e":
break # 跳出整个循环
print(ch) # 输出字符,但不会输出 "a" 和 "e" 之后的字符

2.3 range() 函数

range() 函数用于生成一个数字序列。它有三种用法:

  • range(num):生成从 0 开始到 num-1 的数字序列。
  • range(num1, num2):生成从 num1 开始到 num2-1 的数字序列。
  • range(num1, num2, step):生成从 num1 开始到 num2-1 的数字序列,步长为 step。
1
2
3
4
5
6
7
8
9
# 使用 range() 函数的例子
for x in range(5, 11, 2): # 生成 [5, 7, 9] 这样的序列并遍历它
print(x, end=' ') # 输出每个数字并用空格分隔它们,结果是 5 7 9
print() # 输出一个换行符以美观结束输出

# 另一个例子:倒序输出 10 到 1 的数字序列
for i in range(10, 0, -1): # 生成 [10, 9, 8, ..., 1] 这样的序列并遍历它(注意不包含0)
print(i, end=' ') # 输出每个数字并用空格分隔它们,结果是 10 9 8 7 6 5 4 3 2 1
print() # 同样输出一个换行符以结束输出

函数

函数定义与调用

在Python中,函数是通过def关键字定义的,后面跟函数名和括号内的参数列表。函数体由一系列语句组成,并且使用缩进来表示。

1
2
3
4
def function_name(parameters):
"""Docstring: 函数说明文档"""
# 函数体:由语句组成,执行特定的任务
return result # 可选:返回函数执行的结果

调用函数时,需要在函数名后加上括号和必要的参数。

1
result = function_name(arguments)  # 调用函数,并将返回值存储在变量中(如果有返回值的话)

注:Python不支持函数重载

函数的返回值

如果函数中有return语句,那么函数会返回return后面的值。如果函数中没有return语句或者return语句后面没有跟任何值,那么函数会默认返回None

多返回值

在Python中,函数不仅可以返回单个值,还可以返回多个值。

函数多返回值

当函数需要返回多个值时,可以将这些值以逗号分隔放在return语句后。这些值会被打包成一个元组返回。调用函数时,可以使用多个变量来接收这些返回值。

1
2
3
4
5
def test01():
return 11, 22

x, y = test01()
print(f"x={x}, y={y}") # 输出:x=11, y=22

函数也可以返回不同类型的值:

1
2
3
4
5
def test02():
return 11, 4.5, "14"

x, y, z = test02()
print(f"x={x}, y={y}, z={z}") # 输出:x=11, y=4.5, z=14

函数的参数传递

位置参数

位置参数是按照函数声明中参数的顺序来传递的。

1
2
3
4
def test03(name, age, gender):
print(name, age, gender)

test03('Tom', 10, 'Male') # 输出:Tom 10 Male

关键字参数

关键字参数是通过参数名来指定要传递的参数值。关键字参数可以不按照函数声明中的顺序来传递,但是要注意在函数调用时关键字参数的名称必须与函数声明中的参数名一致。

1
2
3
4
def test04(name, age, gender):
print(name, age, gender)

test04(name='Tom', age=10, gender='Male') # 输出:Tom 10 Male

关键字参数和位置参数可以混用,但位置参数必须放在关键字参数前面。

1
2
3
4
def test05(name, age, gender):
print(name, age, gender)

test05('Tom', age=10, gender='Male') # 输出:Tom 10 Male

缺省参数

缺省参数是指在函数声明时为参数指定一个默认值。如果在函数调用时没有为该参数传递值,则使用默认值。缺省参数必须放在函数声明的最后

1
2
3
4
def test06(name, age, gender="Male"):
print(name, age, gender)

test06('Tom', 10) # 输出:Tom 10 Male

不定长参数

不定长参数是指函数可以接受任意数量的参数。在函数声明中,使用*args来表示接受任意数量的位置参数,使用**kwargs来表示接受任意数量的关键字参数。这些参数在函数内部被收集为一个元组或一个字典。

位置传递(*args)

1
2
3
4
5
6
def test07(*args):
print(args)

test07('Jerry') # 输出:('Jerry',)
test07('Tom', 10) # 输出:('Tom', 10)
test07('Trump', 77, 'Male') # 输出:('Trump', 77, 'Male')

关键字传递(**kwargs)

1
2
3
4
def test08(**kwargs):
print(kwargs)

test08(name='TOM', age=18, id=110) # 输出:{'name': 'TOM', 'age': 18, 'id': 110}

局部变量与全局变量

在函数内部定义的变量是局部变量,只能在该函数内部访问。在函数外部定义的变量是全局变量,可以在任何地方访问,包括函数内部(除非被局部变量覆盖)。

如果需要在函数内部修改全局变量,需要使用global关键字声明。

函数说明文档(Docstring)

函数说明文档是一种特殊的注释,用于解释函数的作用、参数和返回值。它位于函数定义的开始,由三个双引号(可以是三个单引号)包围。

Docstring可以通过help()函数或者函数的__doc__属性查看。

示例代码

下面是一个包含函数定义、调用、局部变量、全局变量和Docstring的示例代码:

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
# 全局变量
num = 200

def strlen(s):
"""
计算字符串的长度
:param s: 输入的字符串
:return: 字符串的长度
"""
length = 0
for char in s:
length += 1
return length

def test_global():
"""
演示全局变量的访问和修改
"""
global num # 声明是全局变量
print(f"Global num before modification: {num}")
num = 500
print(f"Global num after modification: {num}")

def test_local():
"""
演示局部变量的作用范围
"""
local_num = 100 # 局部变量
print(f"Local num: {local_num}")

# 调用函数并打印结果
s1 = "Hello, world!"
print(f"Length of '{s1}': {strlen(s1)}") # 调用strlen函数计算字符串长度并打印结果
test_global() # 调用test_global函数修改全局变量并打印结果
print(f"Global num after test_global function: {num}") # 打印修改后的全局变量值以确认修改生效
test_local() # 调用test_local函数演示局部变量的作用范围(不会修改全局变量)

Python中的数据结构

List——列表

定义列表

在Python中,列表(List)是一种可变的数据容器,可以包含任意类型的对象:数字、字符串、其他列表等。列表中的元素通过逗号分隔,并包含在方括号 [] 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定义一个字符串列表
name_list = ["abc", "def", "ghi"]
print(name_list) # 输出: ['abc', 'def', 'ghi']
print(type(name_list)) # 输出: <class 'list'>

# 列表可以存储多种不同类型的元素
my_list = ["abc", 666, True]
print(my_list) # 输出: ['abc', 666, True]
print(type(my_list)) # 输出: <class 'list'>

# 列表支持嵌套
two_dimension = [[1, 2, 3], [4, 5, 6]]
print(two_dimension) # 输出: [[1, 2, 3], [4, 5, 6]]
print(type(two_dimension)) # 输出: <class 'list'>

下标索引

列表中的元素可以通过下标索引来访问。在Python中,下标从0开始。

1
2
3
4
my_list = ["abc", "def", "ghi"]
print(my_list[0]) # 输出: abc
print(my_list[1]) # 输出: def
print(my_list[2]) # 输出: ghi

尝试访问超出范围的索引会导致IndexError

查找元素

在Python中,你可以使用list.index()函数来查找列表中某个元素的索引。这个函数会返回元素在列表中首次出现的索引,如果元素不在列表中,则会抛出一个ValueError异常。

下面是一个基本的使用示例:

1
2
3
4
5
6
7
8
# 定义一个列表  
my_list = ['apple', 'banana', 'cherry', 'date']

# 查找'banana'的索引
index = my_list.index('banana')

# 输出索引
print(f"The index of 'banana' is {index}")

这段代码会输出:

1
2
bash复制代码
The index of 'banana' is 1

因为在这个列表中,’banana’的索引是1(索引是从0开始的)。

修改元素

列表中的元素可以通过下标索引来修改。

1
2
3
my_list = ["abc", "def", "ghi"]
my_list[1] = "bcd"
print(my_list) # 输出: ['abc', 'bcd', 'ghi']

插入元素

.insert()方法

使用.insert()方法可以在列表的指定位置插入一个元素。

1
2
3
my_list = ["abc", "def", "ghi"]
my_list.insert(1, "666") # 在下标1处插入"666"
print(my_list) # 输出: ['abc', '666', 'def', 'ghi']

.append()方法

使用.append()方法可以在列表的末尾追加一个元素。

1
2
3
my_list = ["abc", "def", "ghi"]
my_list.append("jkl") # 在末尾追加"jkl"
print(my_list) # 输出: ['abc', 'def', 'ghi', 'jkl']

.extend()方法

使用.extend()方法可以在列表的末尾追加另一个容器(例如列表)的所有元素。

1
2
3
my_list = ["abc", "def", "ghi"]
my_list.extend(["jkl", "mno", "pqr"]) # 追加另一个列表的所有元素
print(my_list) # 输出: ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr']

删除元素

del语句

使用del语句可以删除列表中指定位置的元素。

1
2
3
my_list = ["abc", "def", "ghi", "jkl"]
del my_list[1] # 删除下标为1的元素
print(my_list) # 输出: ['abc', 'ghi', 'jkl']

.pop()方法

使用.pop()方法可以删除并返回列表中指定位置的元素。如果不提供索引,则默认删除并返回最后一个元素。

1
2
3
4
my_list = ["abc", "def", "ghi", "jkl"]
element = my_list.pop(1) # 删除下标为1的元素,并将其值赋给element
print(element) # 输出: def
print(my_list) # 输出: ['abc', 'ghi', 'jkl']

.remove()方法

使用.remove()方法可以删除列表中第一个出现的指定元素。如果元素不存在于列表中,则会导致ValueError

1
2
3
my_list = ["abc", "def", "ghi", "jkl"]
my_list.remove("def") # 删除第一个出现的"def"
print(my_list) # 输出: ['abc', 'ghi', 'jkl']

清空列表

使用.clear()方法可以清空列表中的所有元素。

1
2
3
my_list = ["abc", "def", "ghi", "jkl"]
my_list.clear() # 清空列表
print(my_list) # 输出: []

统计元素数量

使用.count()方法可以统计列表中某个元素出现的次数。

1
2
my_list = [1, 2, 3, 2, 1]
print(my_list.count(1)) # 输出: 2,因为1在列表中出现了2次

列表长度

使用内置函数len()可以获取列表的长度(即元素的数量)。

1
2
my_list = [1, 2, 3, 4, 5]
print(len(my_list)) # 输出: 5,因为列表中有5个元素

遍历容器

可以使用for循环来遍历列表中的元素。

1
2
3
my_list = [1, 2, 3, 4, 5]
for ele in my_list:
print(ele, end=" ") # 输出: 1 2 3 4 5

如果需要在遍历过程中同时获取元素的下标和值,可以使用enumerate()函数。

1
2
3
my_list = ["apple", "banana", "cherry"]
for index, item in enumerate(my_list, start=1): # 设置下标从1开始
print(index, item) # 输出元素的下标和值

这将输出:

1
2
3
1 apple
2 banana
3 cherry

如果start=0,将输出

1
2
3
>0 apple
1 banana
2 cherry

Python中列表的拷贝方法

在Python中,拷贝一个列表可以有多种方法,但每种方法都有其特定的用途和后果。本笔记将详细介绍使用赋值运算符(=)、.copy()方法,以及copy模块中的deepcopy()函数进行列表拷贝的区别。

1. 赋值运算符(=

使用赋值运算符并不是真正的拷贝,而是创建了一个新的引用指向同一个列表对象。

1
2
list1 = [1, 2, 3, [4, 5]]
list2 = list1 # 这不是拷贝,list2只是指向list1的引用

在这种情况下,list1list2实际上是指向内存中同一个对象的两个不同名字。任何对list2的修改都会反映到list1上,反之亦然。

1
2
list2.append(6)  # 修改list2
print(list1) # 输出: [1, 2, 3, [4, 5], 6] —— list1也被修改了

2. .copy()方法(浅拷贝)

Python的列表对象有一个.copy()方法,用于创建列表的浅拷贝。这意味着它创建了列表的一个新副本,但副本中的元素仍然是原始列表中元素的引用。

1
2
list1 = [1, 2, 3, [4, 5]]
list2 = list1.copy() # 执行浅拷贝

现在,list1list2是两个不同的列表对象,但它们的元素(特别是可变对象,如内部列表)仍然是共享的。

1
2
list2[3][0] = 'four'  # 修改list2中的内部列表
print(list1) # 输出: [1, 2, 3, ['four', 5]] —— list1也被影响了

尽管list1list2是不同的列表对象,但由于浅拷贝的性质,它们共享对内部列表的引用。

3. deepcopy()函数(深拷贝)

要创建一个完全独立的列表拷贝,包括其所有嵌套对象,应使用copy模块中的deepcopy()函数。深拷贝会递归地复制对象及其所有子对象,生成一个全新的对象树。

1
2
3
4
import copy

list1 = [1, 2, 3, [4, 5]]
list2 = copy.deepcopy(list1) # 执行深拷贝

现在,list2list1的一个完全独立的拷贝,包括所有嵌套对象。

1
2
list2[3][0] = 'four'  # 修改list2中的内部列表
print(list1) # 输出: [1, 2, 3, [4, 5]] —— list1未受影响

修改list2不会影响list1,因为deepcopy()创建了所有对象的独立拷贝。

总结

  • 赋值运算符(=)不创建拷贝,只创建引用。
  • .copy()方法执行浅拷贝,创建新列表但共享嵌套对象
  • deepcopy()函数执行深拷贝,递归地复制所有对象,生成完全独立的对象树。

tuple——元组

和list的区别是不可修改

元组(Tuple)是Python中的一种不可变序列类型,用于存储一系列有序的元素。与列表(List)不同,元组一旦定义,就不能再修改其内容。元组通常用于存储不应该被改变的数据集合。

定义元组

元组使用圆括号()来定义,元素之间使用逗号,分隔。例如:

1
2
3
4
5
6
7
8
9
10
11
# 定义一个包含多个元素的元组
my_tuple = (1, 2, 3, 'hello', 5.5)
print(my_tuple) # 输出:(1, 2, 3, 'hello', 5.5)

# 定义一个空元组
empty_tuple = ()
print(empty_tuple) # 输出:()

# 也可以使用tuple()函数来创建一个空元组
another_empty_tuple = tuple()
print(another_empty_tuple) # 输出:()

注意,如果元组只包含一个元素,那么该元素后面必须跟一个逗号,否则它不会被识别为元组。例如:

1
2
3
4
5
6
7
8
# 定义一个包含单个元素的元组(注意逗号)
single_element_tuple = (42,)
print(single_element_tuple) # 输出:(42,)
print(type(single_element_tuple)) # 输出:<class 'tuple'>

# 如果没有逗号,它会被当作一个普通的表达式,而不是元组
not_a_tuple = (42)
print(type(not_a_tuple)) # 输出:<class 'int'>,因为它被当作了一个整数

元组的不可变性

元组是不可变的,这意味着一旦创建了一个元组,你就不能添加、删除或更改其元素。尝试这样做会导致TypeError。

1
2
3
my_tuple = (1, 2, 3)
# 尝试修改元组(会导致错误)
# my_tuple[0] = 0 # TypeError: 'tuple' object does not support item assignment

然而,如果元组中包含可变对象(如列表),那么这些对象的内容是可以被修改的。但请注意,你不能更改这些可变对象在元组中的身份(即不能用一个新的列表替换原有的列表)。

1
2
3
4
5
6
7
8
# 元组中包含一个列表
my_tuple_with_list = (1, 2, [3, 4, 5])
# 修改列表的内容是可以的
my_tuple_with_list[2][0] = -1
print(my_tuple_with_list) # 输出:(1, 2, [-1, 4, 5])

# 尝试用一个新的列表替换原有的列表(会导致错误)
# my_tuple_with_list[2] = [6, 7, 8] # TypeError: 'tuple' object does not support item assignment

在实际应用中,如果你需要一个不可变的序列来存储数据,并且这些数据在程序的整个生命周期中都不会改变,那么使用元组是一个很好的选择。元组的不可变性也使其在某些情况下比列表更加高效,因为Python可以在内部对其进行优化。

string——字符串

字符串(String)是 Python 中常见的数据容器之一,用于存储字符序列。字符串具有一些独特的特点和操作方法。

字符串的访问

字符串中的字符可以通过下标进行访问。下标从0开始递增,表示从前往后访问字符;而从-1开始递减,则表示从后往前访问字符。

1
2
3
s = "Hello, World!"
print(s[0]) # 输出: H
print(s[-1]) # 输出: !

字符串的不可变性

同元组(Tuple)一样,字符串是一个无法修改的数据容器。一旦一个字符串被创建,就不能修改它的内容。任何对字符串的修改操作都会生成一个新的字符串对象。

字符串方法

index 方法

index 方法用于查找子字符串在字符串中首次出现的位置,并返回该位置的索引。如果子字符串不存在,则会抛出异常

1
2
s = "you are a handsome boy"
print(s.index("hand")) # 输出: 10

replace 方法

replace 方法用于将字符串中的某个子字符串替换为另一个字符串,并返回替换后的新字符串。原始字符串本身不会被修改。

1
2
3
4
s = "cats and dogs are good cats and dogs and cats and dogs do things cats and dogs like do"
s1 = s.replace("cat", "tiger")
print(s) # 输出原始字符串
print(s1) # 输出替换后的新字符串

split 方法

split 方法用于根据指定的分隔符将字符串分割成多个子字符串,并将这些子字符串存储在列表中返回。原始字符串本身不会被修改。

1
2
3
4
s = "cats and dogs are good cats and dogs and cats and dogs do things cats and dogs like do"
l = s.split(" ")
print(s) # 输出原始字符串
print(l) # 输出分割后的列表

strip 方法

strip 方法用于去除字符串开头和结尾的空白字符(包括空格、制表符、换行符等),并返回处理后的新字符串。原始字符串本身不会被修改。如果指定了参数,则会去除前后指定的字符。

1
2
3
4
s = "  12abcde1  "
print(s.strip()) # 输出: "12abcde1"
s = "12abcde1"
print(s.strip("12")) #输出:"abcde"

count 方法

count 方法用于统计某个子字符串在字符串中出现的次数,并返回该次数。

1
2
s = "114514514114514514114114"
print(s.count("114")) # 输出: 4

len 函数

len 函数用于获取字符串的长度,即字符的个数。

1
2
s = "114514514114514514114114"
print(len(s)) # 输出: 24

请注意,虽然 len 是一个内置函数而不是字符串的方法,但它经常用于获取字符串的长度,因此在这里也一并提及。

Python 中常用处理字符串的相关函数

在Python中,字符串是不可变的,但Python提供了很多方法来操作字符串。这些方法可以帮助我们完成各种任务,如查找子字符串,替换子字符串,分割字符串等。下面列出了一些Python中常用的字符串方法:

字符串首字母大写

string.capitalize()

该方法返回字符串的一个副本,其中第一个字符为大写,其余为小写。

计数子字符串

string.count(str, beg=0, end=len(string))

该方法返回子字符串在字符串中出现的次数。可选参数begend是字符串中要开始和结束搜索的索引范围。

检查字符串结束

string.endswith(obj, beg=0, end=len(string))

该方法检查字符串是否以指定的后缀结束,如果是则返回True,否则返回False。可选参数begend指定需要检查的字符串的子集。

查找子字符串

string.find(str, beg=0, end=len(string))

该方法检测字符串中是否包含子字符串str,如果包含则返回开始的索引值,否则返回-1。搜索可以指定开始和结束的索引范围。

类似find但异常

string.index(str, beg=0, end=len(string))

find()方法类似,但如果子字符串不在字符串中,则会引发一个异常。

检查字母和数字

  • string.isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字,则返回True
  • string.isalpha():如果字符串至少有一个字符并且所有字符都是字母,则返回True
  • string.isdecimal():如果字符串只包含十进制数字,则返回True
  • string.isdigit():如果字符串只包含数字,则返回True

检查大小写

  • string.islower():如果字符串中包含至少一个区分大小写的字符,并且所有这些字符都是小写,则返回True
  • string.isupper():如果字符串中包含至少一个区分大小写的字符,并且所有这些字符都是大写,则返回True

其他检查

  • string.isnumeric():如果字符串中只包含数字字符,则返回True
  • string.isspace():如果字符串中只包含空格,则返回True
  • string.istitle():如果字符串是标题化的(即每个单词的首字母大写),则返回True

连接字符串

string.join(seq)

该方法以指定的字符串作为分隔符,将序列中的元素连接成一个新的字符串。

使用加号 + 运算符

1
2
3
4
str1 = "Hello"  
str2 = "World"
str3 = str1 + " " + str2
print(str3) # 输出: Hello World

在这个例子中,我们使用了 + 运算符和空格字符串来连接 str1str2

转换大小写

  • string.lower():将字符串中的所有大写字符转换为小写。
  • string.upper():将字符串中的所有小写字符转换为大写。

去除空格

  • string.lstrip():删除字符串左边的空格。
  • string.rstrip():删除字符串右边的空格(注:该方法未在上文列出,但经常与lstrip()一起使用)。
  • string.strip([obj]):在字符串上同时执行lstrip()rstrip(),删除两端的空格或指定字符。

替换子字符串

string.replace(str1, str2, num=string.count(str1))

该方法把字符串中的str1替换成str2,如果指定了num,则替换不超过num次。

分割字符串

string.split(str="", num=string.count(str))

该方法以指定的分隔符切片字符串,如果指定了num,则仅分隔出num+1个子字符串。

检查字符串开始

string.startswith(obj, beg=0, end=len(string))

该方法检查字符串是否以指定的前缀开始,如果是则返回True,否则返回False

交换大小写

string.swapcase()

该方法翻转字符串中的大小写,即大写变小写,小写变大写。

标题化字符串

string.title()

该方法返回“标题化”的字符串,即所有单词的首字母大写,其余小写。

需要注意的是,字符串的方法很多,而且功能强大,但这里只列出了一些常用的方法。在实际编程中,可以根据需要选择合适的方法来操作字符串。

序列的切片

序列是内容连续、有序,且可以使用下标索引的一类数据容器。在Python中,列表、元组、字符串均可以视为序列。

对序列进行切片操作可以得到序列的一个子序列。切片操作使用冒号(:)分隔的下标索引来实现,基本语法为sequence[start:end:step],其中:

  • sequence表示要进行切片操作的序列。
  • start表示切片操作的起始位置(包含该位置),如果省略则表示从头开始。
  • end表示切片操作的结束位置(不包含该位置),如果省略则表示直到序列末尾。
  • step表示切片操作的步长,即每隔多少个元素取一个,如果省略则表示步长为1。

注意,切片操作不会影响序列本身,而是会得到一个新的序列。

示例

列表切片

1
2
3
4
5
6
7
8
9
mylist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 从索引1开始到索引4之前(不包含索引4)的子序列
result1 = mylist[1:4]
print(result1) # 输出: [1, 2, 3]

# 从索引2开始到索引9之前,每隔2个元素取一个的子序列
result2 = mylist[2:9:2]
print(result2) # 输出: [2, 4, 6, 8]

元组切片

元组的切片操作与列表类似。

1
2
3
4
5
6
7
8
9
mytuple = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

# 从头到尾的子序列(复制整个元组)
r1 = mytuple[:]
print(f"r1={r1}") # 输出: r1=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

# 从尾到头的子序列(反转整个元组)
r2 = mytuple[::-1]
print(f"r2={r2}") # 输出: r2=(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

字符串切片

字符串也可以进行切片操作,得到一个新的字符串。

1
2
3
4
5
6
7
8
9
mystring = "Hello, World!"

# 从索引7开始到末尾的子字符串
result3 = mystring[7:]
print(result3) # 输出: World!

# 从头开始到索引5之前(不包含索引5)的子字符串,每隔2个字符取一个
result4 = mystring[:5:2]
print(result4) # 输出: Hlo

Set——集合

集合是一个无序的、不重复的数据集合。在Python中,集合用花括号{}或者set()函数创建,但由于花括号{}同时用于表示字典,所以空集合必须用set()表示,而不是{}

集合的创建与特性

1
2
3
4
5
6
7
8
9
10
11
12
# 使用花括号创建集合(非空集合)
a = {1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 1, 11}
# 使用set()创建空集合
c = set()

# 打印集合a和c
print(a) # 输出: {1, 2, 3, 4, 5, 6, 11},注意重复元素被自动去除了
print(c) # 输出: set()

# 注意:空的大括号表示字典,不是集合
b = {}
print(type(b)) # 输出: <class 'dict'>

集合的修改

集合是可变的,可以添加或删除元素。

添加元素

使用.add()方法向集合添加元素。

1
2
3
4
a = {11, 2, 3, 4, 5, 6, 7}
a.add(1) # 添加元素1到集合a中
a.add(5) # 添加元素5(已存在,不会重复添加)
print(a) # 输出: {1, 2, 3, 4, 5, 6, 7, 11}

移除元素

使用.remove()方法从集合中移除指定元素;使用.pop()方法随机移除并返回集合中的一个元素。

1
2
3
4
5
6
7
8
9
10
11
a = {11, 2, 3, 4, 5, 6, 7}
a.remove(3) # 移除元素3
print(a) # 输出: {2, 4, 5, 6, 7, 11}

# 使用pop()方法从集合中随机移除元素并打印
a = {11, 2, 3, 4, 5, 6, 7}
while len(a) > 0:
print(a.pop())
# 输出可能是集合a中的任意元素,因为移除是随机的

# 注意:pop()取出的过程对于字符串是随机的,即每次运行结果都不同

集合运算

差集

使用.difference()方法可以得到两个集合的差集,即存在于第一个集合但不存在于第二个集合的元素。

1
2
3
4
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
diff = set1.difference(set2)
print(diff) # 输出: {1, 2, 3},这些元素只存在于set1中

差集并更新左集合

使用.difference_update()方法可以直接更新左集合为差集结果。

1
2
3
4
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
set1.difference_update(set2) # set1现在更新为差集结果
print(set1) # 输出: {1, 2, 3}

并集

使用.union()方法可以得到两个集合的并集,即两个集合中所有不重复的元素。

1
2
3
4
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union_set = set1.union(set2)
print(union_set) # 输出: {1, 2, 3, 4, 5}

集合的长度

使用len()函数可以得到集合中元素的数量。

1
2
a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9}
print(len(a)) # 输出: 9,因为集合自动去除了重复元素

集合的遍历

由于集合不支持下标索引,所以不能使用while循环通过下标来遍历集合。但可以使用for循环直接遍历集合中的元素。

1
2
3
set1 = {1, 2, 3, 4, 5}
for ele in set1:
print(ele, end=" ") # 输出: 1 2 3 4 5(顺序可能不同,因为集合是无序的)

字典——dict

字典(dict)是Python中的一种基本数据结构,用于存储键值对(key-value pairs)。字典是无序的,即元素的插入顺序和迭代顺序可能不一致。字典的键(key)必须是不可变的类型,如整数、浮点数、字符串、元组等,而值(value)可以是任意Python对象。

创建字典

字典可以通过大括号 {}dict() 函数来创建。大括号中,键值对之间用冒号分隔,每对键值对之间用逗号分隔。

1
2
3
d1 = {"a": 97, "b": 98, "c": 99, "d": 100}
d2 = {} # 空字典
d3 = dict() # 通过dict()函数创建空字典

访问字典元素

字典中的元素可以通过键来访问。使用方括号 [] 和键名来获取对应的值。

1
2
d1 = {"a": 97, "b": 98, "c": 99, "d": 100}
print(d1["b"]) # 输出 98

新增和更新字典元素

可以通过方括号 [] 来新增或更新字典中的元素。如果键已经存在,则对应的值会被更新;如果键不存在,则会在字典中新增一个键值对。

1
2
3
d1 = {"a": 97, "b": 98}
d1["c"] = 99 # 新增键值对
d1["a"] = 100 # 更新键"a"对应的值

需要注意的是,字典不支持访问不存在的键,否则会抛出KeyError异常。如果尝试访问不存在的键,可以使用get()方法,该方法允许指定一个默认值。

1
2
d1 = {"a": 97, "b": 98}
print(d1.get("c", "Not Found")) # 输出 "Not Found"

删除字典元素

可以使用pop()方法来删除字典中的元素,并返回被删除元素的值。如果尝试删除不存在的键,pop()方法会抛出KeyError异常,但可以通过提供第二个参数来指定一个默认值

1
2
3
d1 = {"a": 97, "b": 98, "c": 99}
value = d1.pop("b") # 删除键"b"并返回其值
print(value) # 输出 98

另外,clear()方法可以清空字典中的所有元素。

1
2
d1.clear()  # 清空字典
print(d1) # 输出 {}

获取字典的键和值

可以使用keys()方法获取字典中所有的键,values()方法获取所有的值。这两个方法返回的都是视图对象,它们会反映字典的任何更改。

1
2
3
4
5
d1 = {"a": 97, "b": 98, "c": 99}
keys = d1.keys()
values = d1.values()
print(keys) # 输出 dict_keys(['a', 'b', 'c'])
print(values) # 输出 dict_values([97, 98, 99])

遍历字典

字典可以通过多种方式进行遍历。最常见的是遍历所有的键,然后使用键来访问对应的值。

1
2
3
d1 = {"a": 97, "b": 98, "c": 99}
for key in d1:
print(f"key={key}, value={d1[key]}", end=" ")

还可以直接遍历字典的项(键值对),这可以通过items()方法来实现。

1
2
for key, value in d1.items():
print(f"key={key}, value={value}", end=" ")

统计字典元素数量

使用len()函数可以获取字典中元素的数量(键值对的数量)。

1
2
d1 = {"a": 97, "b": 98, "c": 99}
print(len(d1)) # 输出 3

判断元素是否在字典内

可以使用in关键字来判断一个键是否存在于字典中。同样地,not in可以用来判断一个键是否不存在于字典中。

1
2
3
4
5
d1 = {"a": 97, "b": 98, "c": 99}
if "c" in d1:
print("in") # 输出 in
if "p" not in d1:
print("not in") # 输出 not in

容器常用功能

容器之间的转换

转换为列表(list)

在Python中,列表(list)是一种非常常用的数据结构,它可以容纳不同类型的元素,包括数字、字符串、元组、集合甚至字典等。Python提供了便捷的方式将这些容器类型转换为列表。

从元组(tuple)转换

元组与列表非常相似,但元组是不可变的。我们可以使用list()函数将元组转换为列表。

1
2
a1 = (1, 2, 3, 4, 5)
print(list(a1)) # 输出: [1, 2, 3, 4, 5]
从字符串(string)转换

字符串可以被看作字符的序列,因此也可以被转换为列表,每个字符成为列表的一个元素。

1
2
b1 = "abcdefg"
print(list(b1)) # 输出: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
从集合(set)转换

集合是一个无序的不重复元素集,转换为列表后会得到一个包含集合中所有元素的列表。

1
2
c1 = {1, 2, 3, 4, 5}
print(list(c1)) # 输出可能是: [1, 2, 3, 4, 5] (因为集合是无序的,所以实际输出可能不同)
从字典(dictionary)转换

字典转换为列表时,默认只包含字典的键(key)。

1
2
d1 = {"a": 97, "b": 98, "c": 99, "d": 100, "e": 101, "f": 102}
print(list(d1)) # 输出: ['a', 'b', 'c', 'd', 'e', 'f'](字典的键转换为列表)

如果想要同时获取键和值,可以使用items()方法,它会返回一个包含键值对的元组列表。

1
print(list(d1.items()))  # 输出: [('a', 97), ('b', 98), ('c', 99), ('d', 100), ('e', 101), ('f', 102)]

转换为其他类型

当然,Python也允许我们将列表转换为其他类型,如元组、字符串、集合等。

转换为元组(tuple)

使用tuple()函数可以将列表转换为元组。

1
2
lst = [1, 2, 3, 4, 5]
print(tuple(lst)) # 输出: (1, 2, 3, 4, 5)

转换为字符串(string)

在Python中,将列表转化为字符串可以通过多种方式实现。最常见的方法是使用 join() 方法,它可以将列表中的元素连接起来形成一个字符串。以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
my_list = ['Hello', 'world', 'this', 'is', 'a', 'list']  

# 使用空格作为分隔符将列表元素连接成字符串
my_string = ' '.join(my_list)
print(my_string) # 输出:Hello world this is a list

# 如果列表中包含数字或其他非字符串类型,需要先将它们转换为字符串
my_mixed_list = [1, 2, 3, 'apple', 'banana']

# 使用map函数和str将列表中的每个元素转换为字符串,然后再连接
my_string_from_mixed_list = ' '.join(map(str, my_mixed_list))
print(my_string_from_mixed_list) # 输出:1 2 3 apple banana

转换为集合(set)

使用set()函数可以将列表转换为集合,从而去除重复元素。

1
2
lst = [1, 2, 2, 3, 4, 4, 5]
print(set(lst)) # 输出: {1, 2, 3, 4, 5}

排序功能(sorted)

Python的sorted()函数可以对任何可迭代对象进行排序,并返回一个列表。默认情况下,排序是升序的,但可以通过reverse=True参数进行降序排序

1
2
3
a1 = (5, 6, 2, 4, 0)
print(sorted(a1)) # 输出: [0, 2, 4, 5, 6] (升序)
print(sorted(a1, reverse=True)) # 输出: [6, 5, 4, 2, 0] (降序)

对于字符串和字典的排序,sorted()函数会根据元素的字符顺序或键的顺序进行排序。如果想要根据其他标准进行排序,可以使用key参数指定一个函数来提取用于排序的值。

头等函数

函数作为参数传递

在Python中,函数是对象,可以像其他对象一样被传递作为参数。这种能力使得函数变得更加灵活和强大。你可以将函数作为参数传递给其他函数,或者从其他函数中返回函数。

函数作为参数的示例

1
2
3
4
5
6
7
8
9
10
def test_func(compute):
result = compute(1, 2)
print(result)
print(type(compute))

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

# 将add函数作为参数传递给test_func
test_func(add)

输出结果:

1
2
3
<class 'function'>

在这个例子中,test_func接收一个名为compute的函数作为参数,并使用它来计算1和2的和。然后打印结果和compute的类型,显示为<class 'function'>,表明compute确实是一个函数对象。

使用lambda匿名函数作为参数

lambda函数是一种简洁的写函数的方式,它可以在一行内定义简单的函数。lambda函数是匿名的,因为它们没有正式的函数名,但可以将它们赋值给变量,或者以其他方式使用,例如作为函数的参数。

1
2
3
4
5
6
7
def test_func(compute):
result = compute(1, 2)
print(result)
print(type(compute))

# 将lambda函数作为参数传递给test_func
test_func(lambda x, y: x + y)#可以不写出return

输出结果:

1
2
3
<class 'function'>

这里,我们创建了一个lambda函数lambda x, y: x + y,它接收两个参数xy,并返回它们的和。然后我们将这个lambda函数作为参数传递给test_func。输出与前面的例子相同,因为lambda函数的行为与add函数相同。

请注意,在lambda函数中,虽然我们没有明确写出return关键字,但表达式x + y的结果会被自动返回。这是lambda函数的一个特点:它们总是返回表达式的结果。

在Python中,lambda函数是设计为单行表达式函数的,它们只能包含一个表达式,该表达式的值会被返回。因此,lambda函数不支持多行语句或多条指令。如果你想定义一个多行的函数,你应该使用def关键字来定义一个常规函数。

模块

模块的概念

在Python中,模块(Module)是一个包含Python定义和语句的文件。文件名就是模块名加上.py后缀。模块可以被其他程序引入,以使用该模块中的函数、类等功能。模块可以包含可执行的语句和定义函数、类和变量。模块让你能够有逻辑地组织你的Python代码段,实现代码重用。

模块的导入

1. 使用import语句导入整个模块

你可以使用import语句导入整个模块,并通过模块名来访问其中的函数、类、变量等。

1
2
3
4
5
import time  # 导入整个time模块

print(1)
time.sleep(1) # 使用time模块中的sleep函数
print(2)

2. 使用from ... import ...语句导入模块中的特定部分

如果你只需要模块中的某个函数或类,可以使用from ... import ...语句将其导入到当前命名空间中。

1
2
3
4
5
from time import sleep  # 只导入time模块中的sleep函数

print(1)
sleep(1) # 直接使用sleep函数,不需要加模块名前缀
print(2)

3. 使用from ... import *语句导入模块中的所有内容

虽然这种方式可以导入模块中的所有内容,但通常不推荐使用,因为它可能导致命名冲突和不可预见的行为。

1
2
3
4
5
from time import *  # 导入time模块中的所有内容(不推荐)

print(1)
sleep(1) # 直接使用sleep函数,不需要加模块名前缀
print(2)

给模块起别名

如果模块名太长或与其他模块名冲突,你可以使用as关键字给模块起一个别名。

1
2
3
4
5
import time as t  # 给time模块起别名为t

print(1)
t.sleep(1) # 使用别名t来访问time模块中的sleep函数
print(2)

给函数起别名

同样地,你也可以使用as关键字给导入的函数起别名。

1
2
3
4
5
from time import sleep as sl  # 给sleep函数起别名为sl

print(1)
sl(1) # 使用别名sl来调用sleep函数
print(2)

定义自己的模块

自定义模块

在Python中,模块是一个包含Python定义和语句的文件。文件名是模块名加上.py后缀。模块可以被其他程序引入,以使用该模块中的函数、类等。在本例中,我们将创建一个简单的模块,并展示如何在其他文件中导入和使用它。

创建模块

首先,我们创建一个名为greetings.py的模块,它包含一个名为print_hi的函数:

1
2
3
4
5
6
7
# greetings.py

def print_hi(name):
print(f'Hi, {name}')

if __name__ == '__main__':
print_hi('PyCharm')

在这个模块中:

  • 我们定义了一个名为print_hi的函数,它接受一个参数name,并打印出问候语。
  • 我们使用了一个特殊的条件语句if __name__ == '__main__':。当这个模块作为主程序运行时(即直接运行greetings.py文件),这个条件语句下的代码会被执行。因此,它会打印出“Hi, PyCharm”。但是,当这个模块被其他文件导入时,这个条件语句下的代码不会被执行。

导入和使用模块

现在,我们可以在另一个Python文件中导入这个模块,并使用它提供的函数。例如,创建一个名为main.py的文件:

1
2
3
4
5
# main.py

import greetings

greetings.print_hi('Alice')

在这个文件中,我们使用import语句导入了greetings模块,并使用点符号(.)访问模块中的print_hi函数。当我们运行main.py文件时,它会输出“Hi, Alice”。

注意,由于我们在greetings.py文件中使用了if __name__ == '__main__':语句,所以当我们导入这个模块时,它不会自动执行print_hi('PyCharm')语句。因此,输出仅为“Hi, Alice”,而不包括“Hi, PyCharm”。

自定义Python包

什么是Python包

从物理结构上看,Python包就是一个文件夹,它包含一个__init__.py文件,并且该文件夹内可以包含多个模块文件(即.py文件)。这个文件夹的层级结构可以表示包的层级关系。

从逻辑层面来看,包可以看作是一个更大规模的模块,它允许我们将相关的模块组织在一起,形成一个有层次的命名空间。

导入包

在Python中,导入包有几种不同的方式:

方式一:使用import语句

1
import 包名.模块名

使用方式:

1
包名.模块名.目标函数()

方式二:使用from…import语句

1
from 包名 import 模块名

使用方式:

1
模块名.目标函数()

方式三:直接导入目标函数

1
from 包名.模块名 import 目标函数

使用方式:

1
目标函数()

注意

  • 在使用包中的模块或函数之前,需要确保包已经被正确安装或位于Python的搜索路径中。
  • __init__.py文件是包的初始化文件,它可以是空的,也可以包含一些初始化代码或定义__all__变量来指定当使用from 包名 import *时应该导入哪些模块。

安装第三方包

什么是第三方包

第三方包指的是非Python官方提供的包,它们由Python社区中的开发者创建和维护。这些包通常用于解决特定的问题或提供特定的功能,例如数据处理、机器学习、网络编程等。

安装第三方包 - pip

pip是Python的包管理工具,它允许你轻松地安装、升级和卸载Python包。你可以使用pip来安装第三方包。

安装命令

在命令行中,使用以下命令来安装第三方包:

1
pip install 包名称

这将会从Python Package Index(PyPI)下载并安装包。

pip的网络优化

由于pip默认连接的是国外的PyPI源,有时下载速度可能会很慢。你可以通过指定国内的镜像源来加速包的下载。例如,使用清华大学提供的PyPI镜像:

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

或者,你可以永久地修改pip的配置文件,将默认的源替换为国内的镜像源。这样,每次使用pip安装包时都会自动从国内的镜像源下载。

注意

  • 在安装第三方包之前,确保你的Python环境已经正确设置,并且pip工具已经安装。
  • 有些第三方包可能依赖于其他包或特定版本的Python,因此在安装之前最好查看包的文档以了解其依赖关系和要求。
  • 如果你使用的是虚拟环境(virtualenv或conda等),则应在激活虚拟环境后安装第三方包,以确保它们仅在当前虚拟环境中可用。

定义自己的数据类型——类和对象

在Python中,类(Class)是一种抽象数据类型,它定义了包含数据(属性)和方法(函数)的对象的行为和状态。对象是类的实例,它具体地表示了类的属性和行为。

类的定义

类可以通过class关键字来定义,类的名称通常以大写字母开头。类中可以定义属性和方法。

1
2
3
4
5
class Cla:
a = None
b = None
c = None
d = None

在这个例子中,Cla是一个类,它定义了四个类属性abcd,它们都被初始化为None

封装

类中提供了私有成员的形式来支持。

  • 私有成员变量
  • 私有成员方法

定义私有成员的方式非常简单,只需要:

  • 私有成员变量:变量名以__开头(2个下划线)
  • 私有成员方法:方法名以__开头(2个下划线)

即可完成私有成员的设置

对象的创建和属性赋值

要创建一个类的实例(对象),可以使用类名加上括号。然后可以通过点操作符.来访问对象的属性或方法。

1
2
3
4
5
c = Cla()  # 创建一个Cla类的实例对象c
c.a = "abc" # 给对象c的a属性赋值
c.b = 1 # 给对象c的b属性赋值
c.c = 114.514 # 给对象c的c属性赋值
c.d = True # 给对象c的d属性赋值

打印对象c会显示其内存地址,打印type(c)会显示其类型,而打印c.a则会显示其a属性的值。

1
2
3
print(c)       # 输出对象c的内存地址
print(type(c)) # 输出对象c的类型
print(c.a) # 输出对象c的a属性的值

类的方法

类还可以定义方法,方法是类的函数,它可以在类的对象上执行操作。方法的第一个参数总是self,它表示对象本身。

1
2
3
4
5
6
7
8
class Man:
name = None

def say_hi(self):#self是必须填写的,调用类的方法的时候会自动传入该对象
print(f"我是{self.name}")

def say_hi_with_msg(self, msg):
print(f"我是{self.name},{msg}")

在这个例子中,Man类定义了两个方法:say_hisay_hi_with_msg。这两个方法都接受self作为第一个参数,表示对象本身。say_hi方法打印出对象的name属性,而say_hi_with_msg方法则打印出对象的name属性和一个额外的消息。

对象的方法调用

要调用对象的方法,可以使用点操作符.和方法名。如果方法需要参数,可以在方法名后面的括号中提供。

1
2
3
4
he = Man()         # 创建一个Man类的实例对象he
he.name = "某人" # 给对象he的name属性赋值
he.say_hi() # 调用对象he的say_hi方法
he.say_hi_with_msg("hhhhhhh") # 调用对象he的say_hi_with_msg方法并传递一个参数

构造方法

在Python中,类的构造方法是__init__()。当创建类的新实例时,这个方法会自动被调用。构造方法通常用于初始化新创建对象的属性。

示例

下面是一个简单的Student类,它使用构造方法来初始化学生的姓名、年龄和电话号码。

1
2
3
4
5
6
7
8
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel

# 创建一个Student对象
stu = Student("张三", 31, "1145141919810")

在这个例子中,当我们创建stu对象时,__init__方法被调用,并且我们传递的参数(”张三”, 31, “1145141919810”)被用来初始化对象的属性。

魔术方法(Magic Methods)

Python中的魔术方法,也称为特殊方法或双下划线方法,是以双下划线开头和结尾的方法。这些方法有特殊的意义,并且通常在某种特定的操作发生时由Python自动调用。

常见的魔术方法

  • __init__: 构造方法,用于初始化新创建对象的状态。
  • __str__: 返回对象的字符串表示形式,当我们尝试打印对象或使用str()转换对象时调用。
  • __lt__: 定义小于(<)操作符的行为。
  • __le__: 定义小于等于(<=)操作符的行为。
  • __eq__: 定义等于(==)操作符的行为。
示例

下面是一个扩展的Student类,包含了__str____lt____le____eq__魔术方法的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel

def __str__(self):
return f"Student(name={self.name}, age={self.age}, tel={self.tel})"

def __lt__(self, other):
if not isinstance(other, Student):
raise TypeError("Comparison is only implemented for instances of 'Student'")
return self.age < other.age

def __le__(self, other):
if not isinstance(other, Student):
raise TypeError("Comparison is only implemented for instances of 'Student'")
return self.age <= other.age

def __eq__(self, other):
if not isinstance(other, Student):
return False
return self.name == other.name and self.age == other.age and self.tel == other.tel

# 创建Student对象
stu1 = Student("张三", 31, "1145141919810")
stu2 = Student("李四", 30, "1234567890")
stu3 = Student("张三", 31, "1145141919810")

# 使用魔术方法
print(stu1) # 调用 __str__
print(stu1 < stu2) # 调用 __lt__
print(stu1 <= stu2) # 调用 __le__
print(stu1 == stu3) # 调用 __eq__

输出:

1
2
3
4
Student(name=张三, age=31, tel=1145141919810)
False
False
True

注意,在实现比较魔术方法时,我们通常首先检查比较的对象是否也是相同类的实例。如果不是,我们可能会抛出一个TypeError异常或者简单地返回False(对于__eq__方法)。在实现__lt____le__方法时,我们只比较了学生的年龄属性,但根据实际需要,可以比较更多的属性或应用更复杂的逻辑。

继承

在Python中,继承是面向对象编程的一个重要概念,允许我们创建一个类(称为子类或派生类)来继承另一个类(称为父类或基类)的属性和方法。这样,子类可以重用父类的代码,同时还可以添加或覆盖父类的功能。

单继承

单继承是指一个子类只继承一个父类的属性和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Student:
def __init__(self, name, age, tel):
self.name = name
self.age = age
self.tel = tel

def __str__(self):
return f"Student类对象, name = {self.name}, age = {self.age}, tel = {self.tel}"

def __le__(self, other):
if not isinstance(other, Student):
raise TypeError("Comparison is only implemented for instances of 'Student'")
return self.age <= other.age

class Dalao(Student): # Dalao类继承自Student类
GPA = 5.0 # Dalao类新增了一个类属性GPA

# 创建一个Dalao类的实例
d1 = Dalao("王五", 30, "114514")
print(d1.GPA) # 输出Dalao类的GPA属性值

输出:

1
5.0

多继承

多继承是指一个子类可以继承多个父类的属性和方法。在Python中,可以通过在类定义时,在括号内列出多个父类来实现多继承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A:
def method1(self):
print("A method1")

class B:
def method2(self):
print("B method2")

class C(A, B): # C类继承自A类和B类
pass # C类没有新增属性和方法,直接继承A和B的属性和方法

# 创建一个C类的实例
c1 = C()
c1.method1() # 调用继承自A类的方法
c1.method2() # 调用继承自B类的方法

输出:

1
2
A method1
B method2

需要注意的是,多继承可能会引起方法解析顺序(MRO)的问题,Python中使用C3线性化算法来确定方法解析顺序。可以使用类名.mro()类名.__mro__来查看类的MRO列表。

复写和调用父类成员

子类可以复写父类的成员属性和成员方法,即重新定义同名的属性或方法。当子类对象调用成员时,会调用复写后的新成员。如果需要使用被复写的父类成员,可以使用特殊的调用方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Student:
def __init__(self, name, age):
self.name = name
self.age = age

def introduce(self):
print(f"我是{self.name},今年{self.age}岁。")

class GraduateStudent(Student):
def __init__(self, name, age, major):
super().__init__(name, age) # 调用父类的构造函数初始化name和age属性
self.major = major # 新增major属性

def introduce(self): # 复写父类的introduce方法
print(f"我是研究生{self.name},今年{self.age}岁,我的专业是{self.major}。")

# 创建一个GraduateStudent类的实例并调用introduce方法
gs = GraduateStudent("张三", 25, "计算机科学")
gs.introduce() # 调用复写后的新方法输出信息包含专业

输出:

1
我是研究生张三,今年25岁,我的专业是计算机科学。

在上面的例子中,GraduateStudent类复写了Student类的introduce方法,并在其中添加了专业信息。同时,在GraduateStudent类的构造函数中,我们使用super().__init__(name, age)来调用父类的构造函数初始化继承的属性。这样,我们就可以在子类中添加新的属性或方法,同时保留父类的功能。

访问父类成员

直接通过父类名调用

如果要直接通过父类名来调用其成员方法或访问成员变量,可以使用以下语法:

1
2
父类名.成员方法(self, 其他参数)
父类名.成员变量

这里需要注意的是,当直接调用父类的成员方法时,需要显式地将当前对象作为第一个参数传递(通常是self)。

可以对实例化后的对象是用

使用super()调用

super()函数提供了一种动态的方式来访问父类的方法或属性,而不需要显式地引用父类的名字。这在多重继承的场景中特别有用,因为它可以确保正确地调用方法解析顺序(MRO)中的下一个类。

使用super()调用父类成员的语法如下:

1
2
super().成员方法(其他参数)
super().成员变量

注意,在使用super()时,不需要显式地传递self参数,因为super()会自动处理。

在类定义的时候才可以使用

多态性

多态是面向对象编程的三大特性之一,它允许我们使用父类引用来指向子类对象,并且可以调用在子类中重写的方法。在Python中,多态的实现主要依赖于鸭子类型(duck typing)的概念,即不关注对象的实际类型,而是关注对象是否具有所需的方法。

下面我们通过一段代码来演示多态的概念:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Animal:  # 定义一个Animal类作为父类
def speak(self):
pass # 父类中的speak方法为空实现


class Dog(Animal): # Dog类继承自Animal类
def speak(self):
print("汪汪汪") # Dog类中重写speak方法,输出“汪汪汪”


class Cat(Animal): # Cat类继承自Animal类
def speak(self):
print("喵喵喵") # Cat类中重写speak方法,输出“喵喵喵”


class Robot: # 定义一个Robot类,它没有继承自Animal类
def speak(self):
print("滋滋滋") # Robot类中有一个speak方法,输出“滋滋滋”


def make_noise(obj): # 定义一个函数,接受一个对象作为参数
obj.speak() # 调用对象的speak方法


# 创建对象并调用make_noise函数
a = Animal() # 创建Animal对象,但注意Animal类的speak方法为空实现,调用时不会有输出
b = Dog() # 创建Dog对象
c = Cat() # 创建Cat对象
d = Robot() # 创建Robot对象,虽然它没有继承自Animal类,但它有一个speak方法,所以可以在make_noise函数中使用

make_noise(b) # 输出“汪汪汪”
make_noise(c) # 输出“喵喵喵”
# make_noise(a) # 这行代码如果取消注释会运行但没有输出,因为Animal类的speak方法为空实现
make_noise(d) # 输出“滋滋滋”,虽然Robot类没有继承自Animal类,但由于它有一个speak方法,所以可以在make_noise函数中使用,这体现了鸭子类型的思想

注意:在上述代码中,我们实际上并没有使用到a = Animal()这个对象,因为Animal类的speak方法是一个空实现。如果我们尝试调用make_noise(a),它不会产生任何输出。在实际的多态示例中,我们通常会避免创建这样的空实现的父类对象。此外,虽然Robot类没有继承自Animal类,但由于它有一个与Animal类中同名的speak方法,我们仍然可以将其对象传递给make_noise函数并调用其speak方法。这就是鸭子类型的核心思想:不关注对象的实际类型,只关注对象是否具有所需的方法。然而,在严格的面向对象设计中,为了让代码更加清晰和可维护,我们通常会建议将具有相同行为(即具有相同方法)的类组织到一个继承体系中,并通过父类引用来操作子类对象。这样可以确保我们的代码更加符合面向对象的设计原则。在上述示例中,我们可以将Robot类也设计为继承自Animal类(如果逻辑上合理的话),这样就可以更加清晰地展示多态的特性。但是需要注意的是,并不是所有的具有相同方法的类都应该被组织到一个继承体系中。在实际开发中,我们需要根据具体的业务逻辑和设计需求来决定如何组织我们的类和对象。另外需要注意的是,Python中的多态与一些其他语言(如Java)中的多态略有不同。在Python中,由于动态类型和鸭子类型的特性,我们可以在不显式地声明接口或继承体系的情况下实现多态。这使得Python的代码更加灵活和简洁。但是在享受这种灵活性的同时,我们也需要注意保持代码的清晰性和可维护性。

变量的类型注解

在Python 3.5及以后的版本中,引入了类型注解(Type Annotations)的功能。类型注解允许开发者在代码中显式地标注变量、函数参数以及返回值的数据类型。这些注解主要用于帮助开发者编写更加清晰、易于理解的代码,并且为静态类型检查工具、集成开发环境(IDE)等第三方工具提供更好的支持。

类型注解的作用

  1. 代码提示:类型注解可以帮助IDE等开发工具提供更为准确的代码提示和自动补全功能。
  2. 静态类型检查:配合静态类型检查工具,可以在代码运行前发现潜在的类型错误。
  3. 文档化:类型注解也可以作为一种文档形式,帮助其他开发者理解代码中的数据类型。

变量的类型注解

变量的类型注解是在变量名后面加上冒号(:)和类型名。需要注意的是,类型注解仅仅是注释,它不会改变Python的动态类型特性。也就是说,即使你标注了一个变量为整数类型,Python仍然允许你为这个变量赋值为其他类型。

1
2
# 变量类型注解示例
my_var: int = 42 # 标注my_var为整数类型

然而,以下代码虽然类型注解为int,但实际上赋值为字符串类型,Python不会报错,但在静态类型检查时会警告类型不匹配:

1
2
var: int = "itheima"  # 类型注解为int,但实际赋值为str,这不会引发运行时错误
print(var) # 输出:itheima

函数的类型注解

函数的类型注解包括函数参数的类型注解和返回值类型的注解。参数的类型注解写在参数名后面,返回值类型的注解写在函数声明后面的箭头(->)后面。

1
2
3
# 函数类型注解示例
def greet(name: str) -> str:
return f"Hello, {name}!"

在这个例子中,greet函数的参数name被注解为字符串类型,返回值也被注解为字符串类型。

Union用法

当变量或函数参数可以是多种类型之一时,可以使用Union来指定这些类型。Union是从typing模块中导入的。

1
2
3
4
5
6
7
8
9
from typing import Union  

# Union用法示例:变量可以是str或int类型
my_var: Union[str, int] = "Hello" # my_var可以是str类型
my_var = 42 # my_var也可以是int类型,这不会引发运行时错误

# Union用法示例:列表中的元素可以是str或int类型
my_list: list[Union[str, int]] = [1, 2, "itheima", "itcast"]

在这个例子中,my_var被注解为可以是字符串或整数类型,而my_list被注解为一个列表,其中的元素可以是字符串或整数类型。这样,在静态类型检查时,如果这些变量被赋予了不符合注解类型的值,工具就会发出警告。然而,在运行时,Python本身不会因为这些类型注解而引发错误。