Python 变量入门:给数据起个“名字”

你可以把变量想象成一个盒子或者一个标签,我们用它来存放一些数据,比如数字、文字等等。这样,当我们以后想用到这些数据的时候,直接叫这个盒子的名字(也就是变量名)就行了,不用再记住具体的数据是什么。

一、 什么是变量?它有什么用?

1.1 变量就像贴了标签的盒子

现在,你有一个空盒子,你在盒子上贴了一张纸条,上面写着“我的年龄”。然后你把一张写着“18”的小纸条放进了这个盒子。这个贴了“我的年龄”标签的盒子,就可以理解为一个变量。

  • 盒子:代表计算机内存中的一块存储空间。
  • 标签上的名字“我的年龄”:就是我们给变量起的名字(即变量名)。
  • 盒子里的“18”:就是这个变量存储的数据(即变量的值)。

1.2 变量为什么重要?

如果我们没有变量,每次用到“18”这个数字,都得直接写“18”。万一哪天你想把年龄改成“19”,那所有用到“18”的地方都得一个个找出来改,多麻烦啊!有了变量,我们只需要把“我的年龄”这个盒子里的“18”换成“19”,之后所有用到“我的年龄”这个变量的地方,都会自动变成“19”了。是不是很方便?

二、 怎么在 Python 中创建变量?

在 Python 中,创建变量非常简单,不需要像其他有些编程语言那样事先声明:我要一个装数字的盒子或者我要一个装文字的盒子。Python 很聪明,它会自己判断你要装什么类型的数据。

2.1 基本赋值:用等号 = 把数据放进盒子

创建变量的动作,我们叫做赋值。用一个等号 = 来完成。
规则是:等号左边是变量名(也就是盒子的标签),等号右边是你要存的数据(也就是盒子里的东西)。

比如:

1
2
3
4
5
6
7
8
# 我想创建一个叫 counter 的变量,存数字 100
counter = 100 # 这行代码的意思是:把 100 这个整数放进名为 counter 的盒子里

# 我想创建一个叫 miles 的变量,存数字 1000.0 (这里,带小数点的是浮点数,至于什么是浮点数,后面的数据类型会详细讲解)
miles = 1000.0 # 把 1000.0 这个小数放进名为 miles 的盒子里

# 我想创建一个叫 name 的变量,存文字 "John" (这里用引号括起来的是字符串,表示文本)
name = "John" # 把 "John" 这个名字放进名为 name 的盒子里

注意:

  • Python 中,变量必须先赋值,才能使用。你不能凭空叫一个不存在的盒子的名字。
  • 等号 = 在这里的意思是赋值,不是等于。它表示把右边的东西交给左边的变量。

2.2 怎么知道变量里存了啥?用 print() 函数

我们把东西放进盒子了,怎么看看对不对呢?可以用 print() 函数,把变量名放进去,它就会帮我们把盒子里的东西拿出来看看。

比如上面的例子,我们可以这样查看:

1
2
3
print(counter)  # 打印 counter 变量里的内容
print(miles) # 打印 miles 变量里的内容
print(name) # 打印 name 变量里的内容

运行这些代码,你会看到屏幕上输出:

1
2
3
100
1000.0
John

是不是和我们存进去的一样?

三、 变量可以存哪些类型的数据?

虽然我们不需要提前告诉 Python 变量是什么类型,但变量存储的数据本身是有类型的。常见的有:

3.1 整数 (int)

就是我们平时说的整数,比如 100, -5, 0, 999 等等。

1
2
age = 25       # age 里面存的是整数
student_count = 30 # student_count 里面存的是整数

3.2 浮点数 (float)

带小数点的数字,比如 1000.0, 3.14159, -0.5 等等。

1
2
height = 1.75  # 身高 1.75 米,是浮点数
pi = 3.14159 # 圆周率 pi,是浮点数

3.3 字符串 (str)

就是文字、字符。在 Python 中,字符串需要用单引号 ' 或者 双引号 " 括起来。

1
2
3
name = "小明"    # 用双引号
message = 'Hello, Python!' # 用单引号
favorite_color = '蓝色'

Python 里还有其他类型的数据,比如后面会学到的列表、字典等,但这三种是最基础的。

四、 一次创建多个变量

Python 还允许我们一次给多个变量赋值,这在某些情况下很方便。

4.1 多个变量赋同一个值

比如,我想让 abc 这三个变量一开始都存数字 1

1
a = b = c = 1  # 创建一个值为 1 的数据,然后 a, b, c 都指向它,可以理解为三个标签共用一个盒子

现在,a 是 1,b 是 1,c 也是 1。

4.2 多个变量赋不同的值

我想让 x 等于 10y 等于 20z 等于 "你好"

1
x, y, z = 10, 20, "你好"  # 左边变量名用逗号隔开,右边值也用逗号隔开,一一对应

这行代码比分开写三行 x=10; y=20; z="你好" 要简洁一些。

注意: 左边变量的数量和右边值的数量必须一样多,不然会出错!


Python 的标准数据类型

当我们把数据存入变量这个盒子”时,Python 会根据数据的特性,将它们划分成不同的类型。就像我们现实中,盒子里可以放书、放玩具车、放积木一样

Python 有五种最基本、最常用的标准数据类型,它们就像乐高积木的基本块,可以组合出复杂的程序。

这五种标准数据类型是:

  1. Numbers (数字)
  2. String (字符串)
  3. List (列表)
  4. Tuple (元组)
  5. Dictionary (字典)

我们一个个来看。

3.1 Numbers

数字类型,听名字就知道,是用来存储各种数值的数据类型。就像我们数学中用到的数字一样。

3.1.1 数字类型的特点:不可改变

数字类型是不可改变的数据类型。这是什么意思呢?
一旦你创建了一个数字类型的变量,并给它赋了值,比如 a = 5,这个 5 在内存中就固定了。如果你想让 a 变成 6,Python 不会去修改原来那个 5 的值,而是会在内存中重新找一块地方存 6,然后让 a 这个标签指向新的 6。原来的 5 如果没有其他变量指向它,就会被 Python 自动“回收”。

3.1.2 Python 支持的数字类型 (主要关注 Python 3.x)

在 Python 3 中,主要有以下几种数字类型:

  • **int (有符号整数)**:

    • 就是我们日常说的整数,可以是正的、负的,也可以是零。
    • 例如:10, -20, 0, 1000000, -98765
    • Python 3 的 int 类型可以表示任意大小的整数,不像有些语言有长度限制。
  • **float (浮点型)**:

    • 就是带小数点的数字,或者用科学计数法表示的数。
    • 用于表示小数或精度要求不特别高的实数。
    • 例如:3.14, -0.001, 2.5e3 (表示 2.5 × 10³ = 2500.0), 1.0 (虽然是整数,但带了小数点就是 float)
  • **complex (复数)**:

    • 复数由实部虚部组成,形式为 a + bj,其中 a 是实部,b 是虚部,j (或 J) 表示虚数单位。
    • ab 都是浮点数。
    • 例如:3+4j, 10.5-2.3j, -0.1j (等价于 0 - 0.1j), 5j

PS:对于刚接触编程的朋友,intfloat 是最常用的,complex 在特定领域如科学计算中才会用到,初期可以先主要关注前两者。

3.1.3 创建数字类型变量 & del 语句

创建数字类型的变量非常直接,直接赋值即可:

1
2
3
4
age = 25          # age 是 int 类型
height = 1.75 # height 是 float 类型
temperature = -3.5 # temperature 是 float 类型
my_complex = 3 + 4j # my_complex 是 complex 类型

del 语句:删除变量引用
如果你不再需要某个变量了,可以使用 del 语句删除对它的引用。

1
2
3
4
5
x = 10
print(x) # 输出:10

del x # 删除变量 x
print(x) # 这时候再打印 x 就会出错,因为 x 不存在了

del 也可以同时删除多个变量:

1
2
3
4
5
a = 1
b = 2
c = 3
del a, b # 删除 a 和 b
# 现在 a 和 b 不存在了,但 c 还在

Python 2.x 小贴士 (了解即可):
在旧的 Python 2 版本中,还有一种 long (长整型) 类型,用来表示比普通 int 更大的整数。但在 Python 3 中,long 类型被取消了,统一用 int 来表示所有整数,int 可以自动处理任意大的整数。

3.2 String (字符串类型)

字符串,顾名思义,就是由一串字符组成的数据。我们平时看到的文字、符号,都可以用字符串来表示。

3.2.1 字符串是什么样的?

在 Python 中,字符串是用单引号 ' ' 或者 双引号 " " 括起来的字符序列
例如:

1
2
3
4
5
6
7
name = "Alice"       # 双引号
greeting = 'Hello' # 单引号
message = 'I\'m fine' # 单引号内有单引号,需要用反斜杠 \ 转义,或者改用双引号 "I'm fine"
empty_string = "" # 空字符串,里面什么都没有
multi_line = """这是一个
多行的
字符串""" # 三引号 (''' 或 """) 可以用来表示多行字符串

3.2.2 字符串的特点

和数字类型一样,字符串也是不可改变的数据类型。这意味着你不能直接修改字符串中的某个字符。比如说:

1
2
s = "hello"
# s[0] = "H" # 这样做是错误的!会报错!

如果想得到 “Hello”,你需要创建一个新的字符串:

1
2
3
s = "hello"
new_s = "H" + s[1:] # "H" 加上 s 从第2个字符开始到结尾的部分 (ello)
print(new_s) # 输出:Hello

3.2.3 字符串的基本操作

  • 拼接:用 + 号可以将两个字符串连接起来。
    1
    2
    3
    4
    first_name = "张"
    last_name = "三"
    full_name = last_name + first_name # "三" + "张" = "三张" ,在这里,只是演示拼接
    # 或者更正常的 "张" + "三" = "张三"
  • 重复:用 * 号可以将字符串重复多次。
    1
    2
    3
    star = "*"
    line = star * 10 # 重复 10 次 "*"
    print(line) # 输出:**********
  • 索引 (Indexing):字符串中的每个字符都有一个位置编号,叫做索引。我们可以通过索引来访问单个字符。注意:Python 中索引是从 0 开始的!
    1
    2
    3
    4
    s = "Python"
    print(s[0]) # 输出第 1 个字符 'P'
    print(s[1]) # 输出第 2 个字符 'y'
    print(s[5]) # 输出第 6 个字符 'n' ,因为 "Python" 有 6 个字母,索引 0-5
  • **切片 (Slicing)**:通过切片可以获取字符串的一部分(子串)。
    1
    2
    s = "Hello, World!"
    print(s[0:5]) # 从索引 0 开始,到索引 5 之前结束 (不包含 5),输出 "Hello"

3.2 String (字符串类型) - 深入了解

字符串,就是把文字、符号等字符像穿珠子一样串起来形成的序列。在 Python 中,创建字符串非常简单。

3.2.1 如何表示一个字符串?—— 引号大法

在 Python 中,字符串必须用引号括起来。你可以使用:

  • 单引号 ' '
  • 双引号 " "

它们的作用是一样的,选一个你喜欢的用就行。

1
2
3
4
name1 = '小明'    # 单引号
name2 = "小红" # 双引号
print(name1)
print(name2)

为什么要有两种引号?
有时候,字符串里面本身就包含了引号,这时候另一种引号就派上用场了,可以避免混淆。

1
2
3
4
5
# 假设我们要表示 He said, "Hello!" 这句话
sentence1 = 'He said, "Hello!"' # 外面用单引号,里面就可以直接用双引号
sentence2 = "He said, 'Hello!'" # 外面用双引号,里面就可以直接用单引号
print(sentence1)
print(sentence2)

如果字符串里既有单引号又有双引号,或者你坚持要用同一种引号,那么可以使用反斜杠 \ 来转义内部的引号。\ 告诉 Python 后面的那个引号不是字符串的结束标志,而是字符串内容的一部分。

1
2
sentence3 = 'He said, \'I\'m fine.\''  # 用 \' 表示字符串内部的单引号
print(sentence3) # 输出: He said, 'I'm fine.'

三引号 ''' '''""" """
还有一种特殊的三引号,它可以用来表示多行字符串,或者包含了很多单双引号且不想频繁转义的复杂字符串。

1
2
3
4
5
6
7
poem = """
床前明月光,
疑是地上霜。
举头望明月,
低头思故乡。
"""
print(poem) # 会按照原格式(包括换行)输出

3.2.2 字符串的特点:“只读”属性 —— 不可改变

重要!重要!重要! (说三遍)
和数字类型一样,Python 中的字符串也是不可改变的数据类型
这意味着,一旦一个字符串被创建,你就不能直接修改它里面的某个字符。你能做的是创建一个新的字符串。

想象字符串像一个封死的胶囊,里面的内容不能改,但你可以把胶囊里的东西倒出来,加点别的,再装入一个新的胶囊。

1
2
3
4
5
6
7
8
s = "hello"
# 尝试修改第一个字符为 'H'
# s[0] = 'H' # 这行代码会报错!!! TypeError: 'str' object does not support item assignment
print(s)

# 正确的做法:创建一个新的字符串
new_s = 'H' + s[1:] # 'H' 加上 s 中从索引 1 开始到结尾的字符 (ello)
print(new_s) # 输出: Hello

3.2.3 字符串的索引 (Index) - 访问单个字符

字符串是字符的序列,就像一排座位,每个字符都坐在一个固定的位置上。我们可以通过位置编号来访问字符串中的单个字符,这个位置编号就叫做**索引 (Index)**。

关键点:在 Python 中,索引是从 0 开始的! 第一个字符的索引是 0,第二个是 1,依此类推。

1
2
3
4
5
6
s = "Python"  # 字符串 "P" "y" "t" "h" "o" "n"
# 索引: 0 1 2 3 4 5

print(s[0]) # 获取索引为 0 的字符,即第一个字符。输出: P
print(s[1]) # 获取索引为 1 的字符。输出: y
print(s[5]) # 获取索引为 5 的字符。输出: n

如果索引超出了字符串的长度会怎么样?
会报错!IndexError: string index out of range (字符串索引超出范围)。

1
2
s = "Python"  # 长度是 6,索引最大是 5
# print(s[6]) # 这行会报错!

负索引:从右边开始数
除了从左往右从 0 开始,Python 还支持负索引,就是从字符串的右边开始数,最右边的字符是 -1

1
2
3
4
5
6
7
s = "Python"  #  "P"  "y"  "t"  "h"  "o"  "n"
# 正索引: 0 1 2 3 4 5
# 负索引: -6 -5 -4 -3 -2 -1

print(s[-1]) # 获取最后一个字符。输出: n
print(s[-2]) # 获取倒数第二个字符。输出: o
print(s[-6]) # 获取倒数第六个字符 (也就是第一个字符)。输出: P

3.2.4 字符串的切片

有时候我们不需要整个字符串,只想得到它的一部分,比如前3个字符,或者中间某一段,这就是切片

切片的格式:字符串[开始索引 : 结束索引]

  • 开始索引:包含在结果中。
  • 结束索引不包含在结果中。切片会取到 结束索引 - 1 的位置。
  • 切片得到的是一个新的字符串,原字符串不会被改变,因为字符串不可变
1
2
3
4
5
6
7
8
9
10
11
12
s = "Hello, World!"
print(s) # 输出整个字符串: Hello, World!

# 例子1:获取 "Hello"
# "H" "e" "l" "l" "o"
# 0 1 2 3 4
print(s[0:5]) # 从索引 0 开始,到索引 5 结束 ,但不包含 5。输出: Hello

# 例子2:获取 "World"
# ", " "W" "o" "r" "l" "d" "!"
# 5 6 7 8 9 10 11
print(s[7:12]) # 从索引 7 开始,到索引 12 结束。输出: World

切片的省略写法:

  • 如果省略 开始索引,表示从字符串的开头开始取。
    • s[:5] 等价于 s[0:5]
  • 如果省略 结束索引,表示一直取到字符串的末尾(这里也包括最后一个字符)。
    • s[7:] 表示从索引7开始,取到最后。
  • 如果都省略,s[:],表示取整个字符串的副本。
1
2
3
4
s = "Hello, World!"
print(s[:5]) # 输出: Hello ,从开头到索引5之前
print(s[7:]) # 输出: World! 从索引7到结尾
print(s[:]) # 输出: Hello, World! 是整个字符串

步长 (step):跳跃着取
切片还有一个可选参数:步长,格式 字符串[开始索引 : 结束索引 : 步长]。步长默认是 1,表示一个一个挨着取。

1
2
3
4
s = "abcdefghijklmn"
print(s[0:10:2]) # 从0到10,步长2 ,每隔1个取一个。输出: acegi
print(s[::3]) # 从开头到结尾,步长3。输出: adgjm
print(s[::-1]) # 步长为 -1,表示倒序!非常有用!输出: nmlkjihgfedcba

3.2.5 字符串的常用操作

字符串有很多内置的小工具可以使用,也支持一些运算符。

(1)字符串拼接 - +

+ 号可以把两个或多个字符串“粘”在一起,形成一个新的字符串。

1
2
3
4
greeting = "Hello"
name = "Alice"
message = greeting + ", " + name + "!" # "Hello" + ", " + "Alice" + "!"
print(message) # 输出: Hello, Alice!

注意:+ 号两边必须都是字符串才能拼接。你不能直接把字符串和数字用 + 拼接。

1
2
3
4
age = 18
# print("我今年" + age + "岁了") # 这行会报错!因为 age 是整数。
# 正确做法:把数字转换成字符串 str(age)
print("我今年" + str(age) + "岁了") # 输出: 我今年18岁了
(2)字符串重复 - *

* 号可以让一个字符串重复多次。

1
2
3
4
5
6
7
star = "*"
line = star * 10 # 把 "*" 重复 10 次
print(line) # 输出: **********

laugh = "haha"
big_laugh = laugh * 3 # "haha" *3 = "hahahahaha"
print(big_laugh) # 输出: hahahahahaha
(3)获取字符串长度 - len() 函数

len() 是一个内置函数(不是字符串独有的,但字符串常用),它可以返回字符串中字符的个数,也就是字符串的长度。

1
2
3
4
5
6
s = "Hello"
length = len(s)
print(length) # 输出: 5

empty = ""
print(len(empty)) # 输出: 0 ,因为空字符串长度为0

3.3 List ,列表类型

列表(List)是 Python 中使用最频繁的数据类型之一,你可以把它想象成一个超级灵活的“集装箱” 或者一个有序的队伍。这个集装箱里可以装任何东西:数字、字符串、甚至是另一个列表(这叫嵌套),而且顺序是固定的,我们还可以随时往里加东西、减东西、改东西。

3.3.1 列表长什么样?—— 中括号 [] 来标识

列表使用 中括号 [] 来创建,列表中的元素之间用 逗号 , 分隔。

1
2
3
4
5
6
7
8
9
10
11
# 一个装水果名称的列表
fruits = ['apple', 'banana', 'cherry', 'date']
print(fruits)

# 一个装数字的列表
numbers = [1, 2, 3, 4, 5]
print(numbers)

# 一个“大杂烩”列表:可以包含不同类型的元素
mixed_list = ['Hello', 42, 3.14, True, fruits] # 甚至包含了上面的 fruits 列表!
print(mixed_list)

3.3.2 列表的特点:

  1. 有序性:列表中的元素有明确的顺序,每个元素都有自己的位置
  2. 可变性 (Mutable):这是列表非常重要的一个特点!我们可以修改列表中的元素值,可以添加新元素,也可以删除已有元素。这和我们之前学的数字、字符串的“不可变性”形成了鲜明对比
  3. 元素多样性:列表中的元素可以是不同类型的,整数、浮点数、字符串、布尔值、甚至其他列表或对象

3.3.3 访问列表元素 - 和字符串索引、切片很像!

因为列表是有序的,所以我们可以通过索引 来访问列表中的单个元素,也可以通过切片 来访问列表的一个子序列。这和字符串的索引、切片操作几乎完全一样!

索引规则:

  • 从左往右:第一个元素的索引是 0,第二个是 1,依此类推。
  • 从右往左:最后一个元素的索引是 -1,倒数第二个是 -2,依此类推。
1
2
3
4
5
6
7
8
9
10
11
12
13
fruits = ['apple', 'banana', 'cherry', 'date']

# 访问列表中的第一个元素
print(fruits[0]) # 输出: apple

# 访问列表中的第二个元素
print(fruits[1]) # 输出: banana

# 访问列表中的最后一个元素
print(fruits[-1]) # 输出: date

# 访问列表中的倒数第二个元素
print(fruits[-2]) # 输出: cherry

切片规则:列表[开始索引 : 结束索引 : 步长]

  • 开始索引:包含在结果中。
  • 结束索引不包含在结果中。
  • 步长:每隔多少个元素取一个,默认是 1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 切片:从索引 2 开始到索引 5 结束
print(numbers[2:5]) # 输出: [2, 3, 4]

# 切片:从索引 3 开始到列表末尾
print(numbers[3:]) # 输出: [3, 4, 5, 6, 7, 8, 9]

# 切片:从列表开头到索引 5 结束
print(numbers[:5]) # 输出: [0, 1, 2, 3, 4]

# 切片:步长为 2 (隔一个取一个)
print(numbers[0:10:2]) # 输出: [0, 2, 4, 6, 8]

# 切片:步长为 -1 (倒序)
print(numbers[::-1]) # 输出: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 非常有用!

# 切片:列表也可以嵌套
nested_list = [1, 2, [3, 4, 'a'], 5]
print(nested_list[2]) # 输出: [3, 4, 'a'] 取出第三层的小列表
print(nested_list[2][2]) # 输出: 'a' 先取小列表,再取小列表的第三个元素

3.3.4 修改列表元素 - 直接赋值!

正是因为列表是“可变的”,所以我们可以直接通过索引来修改列表中某个位置的元素。

1
2
3
4
5
6
7
8
9
10
11
colors = ['red', 'green', 'blue']
print("修改前:", colors) # 输出: 修改前: ['red', 'green', 'blue']

# 修改第二个元素
colors[1] = 'yellow'
print("修改后:", colors) # 输出: 修改后: ['red', 'yellow', 'blue']

# 也可以修改切片
numbers = [1, 2, 3, 4, 5]
numbers[1:3] = ['a', 'b', 'c'] # 把索引 1-2 的元素替换成 ['a','b','c']
print(numbers) # 输出: [1, 'a', 'b', 'c', 4, 5]

对比字符串:你能直接修改字符串中的某个字符吗?不能!s = "hello"; s[0] = "H" 会报错。但列表可以!

3.3.5 列表的常用操作

(1)列表连接 (拼接) - +

和字符串一样,+ 号可以将两个列表连接起来,形成一个新的列表。原列表不会被改变。

1
2
3
4
5
6
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
combined_list = list1 + list2
print(combined_list) # 输出: [1, 2, 3, 'a', 'b', 'c']
print(list1) # 输出: [1, 2, 3] list1 本身没变
print(list2) # 输出: ['a', 'b', 'c'] list2 本身也没变
(2)列表重复 - *

和字符串一样,* 号可以将列表中的元素重复多次,形成一个新的列表。

1
2
3
numbers = [0, 1]
repeated = numbers * 3
print(repeated) # 输出: [0, 1, 0, 1, 0, 1]
(3)获取列表长度 - len() 函数

len() 函数同样适用于列表,返回列表中元素的个数。

1
2
fruits = ['apple', 'banana', 'cherry']
print(len(fruits)) # 输出: 3
(4)步长参数在列表切片中的应用

我们之前在字符串切片中见过步长,列表切片也完全支持。

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

# 从索引 1 到索引 8 ,步长为 2 每隔一个取一个
sub_list = numbers[1:8:2]
print(sub_list) # 输出: [1, 3, 5, 7]

# 步长为负数,从后往前跳着取
reverse_step = numbers[8:1:-2]
print(reverse_step) # 输出: [8, 6, 4, 2]

3.4 Tuple——元组类型

元组 (Tuple) 是 Python 中的另一个重要序列类型,它和我们刚刚学过的列表 (List) 非常相似,但又有一个关键的区别。

3.4.1 元组长什么样?—— 小括号 () 来标识

元组使用 小括号 () 来创建,元组中的元素之间同样用 逗号 , 分隔。

1
2
3
4
5
6
7
8
9
10
11
# 一个装城市名称的元组
cities = ('Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen')
print(cities)

# 一个装数字的元组
coordinates = (10.5, 20.3) # 比如表示一个二维坐标 (x, y)
print(coordinates)

# 一个“大杂烩”元组:也可以包含不同类型的元素
mixed_tuple = ('Hi', 100, 3.14, True, cities) # 也可以包含列表或其他元组
print(mixed_tuple)

一个特殊情况:创建只有一个元素的元组
如果元组中只有一个元素,**必须在这个元素后面加上一个逗号 ,**,否则 Python 会把它当成一个普通的括号表达式,而不是元组。

1
2
3
4
5
6
7
single_tuple1 = (5)       # 这不是元组!这只是一个整数 5 加上括号
single_tuple2 = (5,) # 这才是元组!元素后面有逗号
single_tuple3 = 'a', # 甚至可以不加括号,直接写 'a', 也是一个元组 .但是不推荐,可读性差

print(type(single_tuple1)) # 输出: <class 'int'>
print(type(single_tuple2)) # 输出: <class 'tuple'>
print(type(single_tuple3)) # 输出: <class 'tuple'>

3.4.2 元组的特点:

  1. 有序性:和列表一样,元组中的元素有明确的顺序,每个元素都有自己的位置。
  2. 不可变性 (Immutable):这是元组和列表最根本的区别!一旦一个元组被创建,你就不能修改它里面的元素值,不能添加新元素,也不能删除已有元素。是不是想到了字符串和数字?
  3. 元素多样性:和列表一样,元组中的元素也可以是不同类型的

3.4.3 访问元组元素 - 和列表、字符串的索引、切片完全一样!

因为元组也是有序的序列,所以访问元组元素的方式和列表、字符串完全相同——使用索引 (Index) 访问单个元素,使用切片 (Slicing) 访问子序列。

索引规则:

  • 从左往右:第一个元素的索引是 0
  • 从右往左:最后一个元素的索引是 -1
1
2
3
4
5
6
7
8
9
10
languages = ('Python', 'Java', 'C++', 'JavaScript')

# 访问元组中的第一个元素
print(languages[0]) # 输出: Python

# 访问元组中的第三个元素
print(languages[2]) # 输出: C++

# 访问元组中的最后一个元素
print(languages[-1]) # 输出: JavaScript

切片规则:元组[开始索引 : 结束索引 : 步长]

  • 开始索引:包含。
  • 结束索引:不包含。
  • 步长:默认 1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
numbers_tuple = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

# 切片:从索引 1 到索引 4
print(numbers_tuple[1:4]) # 输出: (1, 2, 3)

# 切片:从索引 5 开始到末尾
print(numbers_tuple[5:]) # 输出: (5, 6, 7, 8, 9)

# 步长为 2
print(numbers_tuple[::2]) # 输出: (0, 2, 4, 6, 8)

# 嵌套元组的访问
nested_tuple = (1, (2, 3, 'a'), 4)
print(nested_tuple[1]) # 输出: (2, 3, 'a') 取出里面的小元组
print(nested_tuple[1][2]) # 输出: 'a'

3.4.4 修改元组元素?

元组是不可变 (Immutable) 的! 这是元组和列表最核心的区别。一旦创建,元组的内容就不能被修改

1
2
3
4
5
6
fruits_tuple = ('apple', 'banana', 'cherry')
print("修改前:", fruits_tuple)

# 尝试修改元组中的第二个元素
# fruits_tuple[1] = 'orange' # 这行代码会报错!!!
# 错误信息类似:TypeError: 'tuple' object does not support item assignment

你也不能直接给元组的切片赋值来修改它,或者删除它的元素。

1
2
# 尝试删除元组元素
# del fruits_tuple[0] # 同样会报错!

3.4.5 元组的常用操作

因为元组不可变,所以很多修改性的操作都不能做。但一些非修改性的操作和列表类似。

(1)元组连接 (拼接) - +

+ 号可以将两个元组连接起来,形成一个新的元组原有的元组不会被改变

1
2
3
4
5
6
tuple1 = (1, 2, 3)
tuple2 = ('a', 'b', 'c')
combined_tuple = tuple1 + tuple2
print(combined_tuple) # 输出: (1, 2, 3, 'a', 'b', 'c')
print(tuple1) # 输出: (1, 2, 3) (tuple1 本身没变)
print(tuple2) # 输出: ('a', 'b', 'c') (tuple2 本身也没变)
(2)元组重复 - *

* 号可以将元组中的元素重复多次,形成一个新的元组

1
2
3
simple_tuple = ('x', 'y')
repeated_tuple = simple_tuple * 3
print(repeated_tuple) # 输出: ('x', 'y', 'x', 'y', 'x', 'y')
(3)获取元组长度 - len() 函数

len() 函数同样适用于元组,返回元组中元素的个数。

1
2
fruits_tuple = ('apple', 'banana', 'cherry')
print(len(fruits_tuple)) # 输出: 3

3.4.6 元组 vs 列表:我该用哪个?

既然元组和列表这么像,而且元组还不能修改,感觉好像不如列表好用?为什么还要有元组呢?

元组存在的价值在于其不可变性带来的好处:

  1. 安全性:如果某些数据在程序运行过程中不应该被修改(比如一些配置信息、坐标点、固定的选项等),用元组可以防止意外修改。
  2. 效率:元组的创建和访问速度通常比列表要快一点点,因为它更简单。
  3. 可哈希性:元组(假如,其所有元素都可哈希)可以作为字典的键,而列表不行(这里不理解也没关系,后面学习字典会讲)
  4. 函数返回值:Python 函数可以很方便地返回一个元组,从而实现返回多个值的效果。

一句话总结:

  • 如果你需要存储一组数据,并且可能会对其进行添加、删除、修改等操作,选择列表 (List)
  • 如果你需要存储一组数据,并且这组数据 一旦创建就不应被修改,或者你需要上述元组的优点,选择 元组 (Tuple)

元组的许多用法都和列表相似,最大区别就在于不可变性

3.5 Dictionary (字典类型)

字典(Dictionary)是 Python 中除列表之外最灵活、也非常常用的内置数据结构。如果你熟悉其他语言,它类似于 “哈希表 (Hash Table)” 或 “关联数组 (Associative Array)”。

思考一个问题: 列表、元组是通过位置(索引) 来访问元素的。如果元素很多,或者我们想通过有意义的名字来快速找到某个值,该怎么办呢?

这就是字典的用武之地!字典是一种键值对 ** 的集合。你可以把它看作成一本通讯录**:

  • **键 (key)**:就像通讯录里的 人名 (这是唯一的,不能重复的)。
  • **值 (value)**:就像通讯录里这个人对应的 电话号码/地址 (它们可以是任何类型的数据,并且可以重复)。

我们通过 “键” 来快速查找和访问对应的 “值”

3.5.1 字典长什么样?—— 花括号 {} 来标识

字典使用 花括号 {} 来创建。

  • 每个键值对的格式是:键: 值 (key: value)。
  • 多个键值对之间用 逗号 , 分隔。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 一个表示人的基本信息的字典
person = {
"name": "Alice", # 键 "name",值 "Alice"
"age": 30, # 键 "age",值 30
"city": "New York" # 键 "city",值 "New York"
}
print(person)

# 一个简单的电话簿字典
phone_book = {
"John": "123-4567",
"Jane": "987-6543",
"Bob": "555-1234"
}
print(phone_book)

3.5.2 字典的特点:

  1. 键值对集合:元素以 key: value 的形式存在。
  2. 无序性 (注意:Python 3.7+ 版本的字典已经保证了插入顺序,但访问方式仍不是通过索引):字典中的元素没有固定的顺序,我们不能通过位置索引来访问,只能通过 key 来访问。最新的 Python 版本虽然保留了插入顺序,但这不是字典的核心特性,不应依赖索引操作字典。
  3. 键的唯一性:字典中的 key 必须是唯一的。如果出现重复的 key,后面的 value 会覆盖前面的。
  4. 键的不可变性:**key 必须是不可变的数据类型,比如:字符串、数字、元组。列表不能作为 key**,因为列表是可变的。
  5. 值的任意性:**value 可以是任何类型的数据**:数字、字符串、列表、字典、元组等,并且可以重复。
  6. 可变性:字典本身是可变的,可以随时添加、修改或删除键值对。

3.5.3 访问字典中的值 - 通过 来访问!

要获取字典中某个 key 对应的 value,使用 方括号 [] 并传入 key
字典名[键]

1
2
3
4
5
6
7
person = {"name": "Alice", "age": 30, "city": "New York"}

# 访问 "name" 对应的值
print(person["name"]) # 输出: Alice

# 访问 "age" 对应的值
print(person["age"]) # 输出: 30

如果访问一个不存在的 key,会怎么样?
会报错!KeyError: '不存在的键'

1
# print(person["salary"])  # 键 "salary" 不存在,会报错:KeyError: 'salary'

避免 KeyError 的小技巧:使用 get() 方法
字典对象有一个 get() 方法,它也可以通过 key 获取 value。如果 key 不存在,它不会报错,而是返回 None ,或者你指定的默认值

1
2
3
4
# 使用 get() 方法获取值
print(person.get("name")) # 输出: Alice,和 person["name"] 效果一样
print(person.get("salary")) # 输出: None,因为 "salary" 不存在
print(person.get("salary", 0)) # 输出: 0,如果 "salary" 不存在,返回指定的默认值 0

3.5.4 修改字典中的值 - 通过 直接赋值!

字典是可变的,我们可以通过 来修改对应的值。格式:字典名[键] = 新值

1
2
3
4
5
6
7
8
9
10
person = {"name": "Alice", "age": 30, "city": "New York"}
print("修改前:", person)

# 修改 "age" 的值
person["age"] = 31 # 将键 "age" 对应的值改为 31
print("修改后:", person)

# 如果 key 不存在,赋值操作会变成添加新的键值对
person["email"] = "alice@example.com" # 新增键值对 "email": "alice@example.com"
print("添加新键值对后:", person)

3.5.5 字典的常用操作

(1)添加新的键值对

如上面所见,直接对一个新的 key 进行赋值,就会在字典中添加这个新的键值对。

1
2
3
person = {"name": "Alice"}
person["hobby"] = ["reading", "traveling"] # 值可以是列表
print(person) # 输出: {'name': 'Alice', 'hobby': ['reading', 'traveling']}
(2)删除键值对 - del 语句 或 pop() 方法
  • del 字典名[键]: 删除指定 key 对应的键值对。如果 key 不存在,会报错。
  • 字典名.pop(键): 删除指定 key 对应的键值对,并返回被删除的值。如果 key 不存在,可指定默认值避免报错。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
person = {"name": "Alice", "age": 30, "city": "New York"}
print("原始字典:", person)

# 使用 del 删除
del person["age"]
print("删除 'age' 后:", person)

# 使用 pop() 删除,并获取被删除的值
city = person.pop("city")
print("被删除的 'city' 值是:", city)
print("删除 'city' 后:", person)

# pop() 可以指定默认值
salary = person.pop("salary", "Not Found") # "salary" 不存在,返回 "Not Found"
print(salary)
(3)获取所有的键、所有的值、所有的键值对

字典提供了方法来获取其所有的键、值或键值对:

  • 字典名.keys(): 返回一个包含所有键的**视图对象 (view object)**,可以转成列表。
  • 字典名.values(): 返回一个包含所有值的视图对象,可以转成列表。
  • 字典名.items(): 返回一个包含所有键值对的视图对象,每个键值对是一个 (key, value) 元组,可以转成列表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
phone_book = {"John": "123-4567", "Jane": "987-6543", "Bob": "555-1234"}

# 获取所有键
all_keys = phone_book.keys()
print("所有键:", all_keys) # 输出类似: dict_keys(['John', 'Jane', 'Bob'])
print("所有键 (转成列表):", list(all_keys)) # 输出: ['John', 'Jane', 'Bob']

# 获取所有值
all_values = phone_book.values()
print("所有值:", all_values) # 输出类似: dict_values(['123-4567', '987-6543', '555-1234'])
print("所有值 (转成列表):", list(all_values)) # 输出: ['123-4567', '987-6543', '555-1234']

# 获取所有键值对
all_items = phone_book.items()
print("所有键值对:", all_items) # 输出类似: dict_items([('John', '123-4567'), ('Jane', '987-6543'), ('Bob', '555-1234')])
print("所有键值对 (转成列表):", list(all_items)) # 输出: [('John', '123-4567'), ('Jane', '987-6543'), ('Bob', '555-1234')]
(4)检查一个键是否在字典中 - in 运算符

使用 in 关键字可以判断一个 key 是否存在于字典中。

1
2
3
person = {"name": "Alice", "age": 30}
print("name" in person) # 输出: True (键 "name" 存在)
print("salary" in person) # 输出: False (键 "salary" 不存在)
(5)获取字典长度 - len() 函数

len() 函数同样适用于字典,返回字典中键值对的数量

1
2
person = {"name": "Alice", "age": 30, "city": "New York"}
print(len(person)) # 输出: 3 (有 3 个键值对)

3.5.6 字典的键 (key) 的规则

  • 唯一性:同一个字典中,key 不能重复。如果重复定义,后面的 value 会覆盖前面的。
    1
    2
    dict_with_duplicate_keys = {"a": 1, "b": 2, "a": 3}
    print(dict_with_duplicate_keys) # 输出: {'a': 3, 'b': 2} (前面的 "a":1 被覆盖了)
  • 不可变性key 必须是不可变的数据类型
    • 合法的 key:字符串 ("name"), 数字 (123), 元组 ((1,2) 如果元组内元素都是不可变的
    • 不合法的 key:列表 ([1,2]), 字典 ({}) 。因为它们是可变的
      1
      2
      3
      4
      5
      6
      7
      8
      valid_dict = {
      "string_key": "value",
      123: "number_key",
      (1, 2): "tuple_key"
      }
      print(valid_dict)

      # invalid_dict = {[1, 2]: "list_key"} # 这行会报错!因为列表不能作为 key。TypeError: unhashable type: 'list'

恭喜你!到目前为止,我们已经学习了 Python 最核心的几种数据类型:数字 (int, float)字符串 (str)布尔值 (bool)列表 (list)元组 (tuple) 和 **字典 (dict)**。这些是你编写 Python 程序的基石。

Python 基础数据类型小测验

一、选择题 (每题5分,共30分)

  1. 下列哪种数据类型在 Python 中是不可变的?( )
    A. 列表 (List)
    B. 元组 (Tuple)
    C. 字典 (Dictionary)
    D. 以上都是

  2. 要创建一个包含元素 1, 2, 3 的元组,下面哪种写法是正确的?( )
    A. (1, 2, 3)
    B. [1, 2, 3]
    C. {1, 2, 3}
    D. 1, 2, 3 (不加括号)

  3. 对于字典 person = {"name": "Alice", "age": 25}, 要获取 "Alice" 的值,应该使用哪种方式?( )
    A. person[0]
    B. person["name"]
    C. person.get("Alice")
    D. person.values()[0]

  4. 执行语句 my_list = [1, 2, 3]; my_list.append(4) 后,my_list 的值是?( )
    A. [1, 2, 3]
    B. [4, 1, 2, 3]
    C. [1, 2, 3, 4]
    D. 报错,因为列表不支持 append 方法

  5. str(123) + "abc" 的结果是?( )
    A. 123abc (字符串类型)
    B. 123abc (整数类型)
    C. 123 + abc (字符串类型)
    D. 报错,因为整数不能和字符串相加

  6. 下列哪个函数可以将字符串 "123.45" 转换为浮点数 123.45?( )
    A. int()
    B. float()
    C. str()
    D. number()

二、看程序写结果 (每题10分,共20分)

  1. 写出下面代码的输出结果:

    1
    2
    3
    my_tuple = (10, 20, 30, 40)
    print(my_tuple[1])
    print(my_tuple[-2])
  2. 写出下面代码的输出结果:

    1
    2
    3
    4
    5
    6
    student = {
    "name": "Bob",
    "grades": [90, 85, 95]
    }
    student["grades"].append(88)
    print(student["grades"])

三、编程题 (每题10分,共50分)

  1. 创建列表并访问:创建一个名为 fruits 的列表,包含元素 "apple", "banana", "cherry",然后打印列表的第二个元素(索引为1的元素)。

  2. 修改字典:有字典 car = {"brand": "Toyota", "year": 2020},请将 "year" 的值修改为 2023,并打印修改后的字典。

  3. 列表切片:有列表 numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],请使用切片获取列表中从索引 2 到索引 5(不包含5)的元素,并打印结果。

  4. 简单类型转换:用户输入一个数字(例如 "5"),请将其转换为整数后乘以 2,并打印结果。
    提示:用 input() 获取输入,用 int() 转换。

  5. **字典遍历基础 (选做,有难度)**:有字典 scores = {"math": 90, "english": 85, "science": 95},请打印出所有学科的名称(即字典的所有键)。
    提示:使用 keys() 方法。