引言
变量 是您将编写的几乎每个 Python 程序的基础。没有它们,您无法存储用户输入、保存计算结果,或在条件语句和 for 循环之间传递数据。本教程涵盖 Python 3 中的变量基础:如何声明和重新赋值、命名规则和约定、数据类型和 type() 函数、作用域、常量,以及常见错误,以便您能自信地在自己的代码中使用变量。
先决条件
- 您应该已安装 Python 3。
- 您应该已在计算机或服务器上设置编程环境。
- 如果您尚未设置编程环境,请参阅以下指南:
- 本地编程环境。
- 服务器上的编程环境,适用于您的操作系统(如 Ubuntu、CentOS、Debian 等)。
关键要点
- 变量是引用值的名称;使用
name = value声明它们。不需要类型声明。 - 名称必须是一个单词,仅使用字母、数字和下划线,且不能以数字开头。约定使用 snake_case。
- 使用
type()检查变量的类型。Python 使用动态类型,并在赋值时推断类型。 - 您可以重新将变量赋值为新值(和新类型)。不可变类型无法原地更改;可变类型可以原地修改。
- 优先使用局部变量;仅在必要时使用
global。常量使用 SCREAMING_SNAKE_CASE 命名;typing.Final可以文档化不可重新赋值。 - 避免大小写拼写错误、无意重新赋值、在赋值前使用变量,以及遮蔽内置函数如
list或str。
Python 中的变量是什么?
变量 是一个符号名称,引用存储在内存中的值。您在代码中使用变量名来读取或更新该值,而不是重复该值本身。
您可以将变量视为贴在值上的标签。例如,将整数 103204934813 存储在变量中,让您可以重复使用它而无需重新输入数字:
信息: 要跟随示例,请使用 python3 命令打开 Python 交互式 shell,并在 >>> 提示符后运行示例。
my_int = 103204934813
print(my_int)
103204934813
该标签名称为 my_int,并绑定到整数 103204934813。变量让您可以使用名称进行数学运算和其他操作:
print(my_int - 813)
103204934000
如何在 Python 中声明变量
在 Python 中声明变量时,编写变量名、赋值运算符 = 和值。不需要单独的声明或类型关键字。
赋值语句 有三个部分:变量名、赋值运算符 = 和值。它们一起创建(或初始化)变量。例如:
x = 76 + 145
print(x)
221
变量 x 被设置为 76 + 145 的结果,即 221。在 Python 中,变量必须始终位于 = 的左侧;表达式会被求值,然后绑定到名称。赋值后,您可以立即开始使用该变量。
如果您翻转赋值运算符两侧会发生什么:
76 = x
SyntaxError: cannot assign to literal
变量必须始终位于 = 的左侧;将值放在左侧会导致 SyntaxError。
在 Python 中,在您为其赋值之前,变量并不存在。没有办法仅声明变量名而不赋予它值。如果您在赋值之前引用一个名称,Python 会引发 NameError。
print(my_variable)
my_variable = 10
NameError: name 'my_variable' is not defined
在当前作用域中,任何对该名称的引用之前必须先进行赋值。
如果您需要在有有效值之前让变量名存在,请将其赋值为 None。None 是 Python 表示值缺失的方式。
result = None
print(result)
print(type(result))
None
<class 'NoneType'>
一旦可用(例如计算或用户输入后),您可以稍后将 result 重新赋值为真实值。
命名规则和约定
变量名必须是一个单词(无空格),只能包含字母、数字和下划线,并且不能以数字开头。
下表总结了有效和无效的名称:
| 有效 | 无效 | 无效原因 |
|---|---|---|
my_int |
my-int |
不允许使用连字符 |
int4 |
4int |
不能以数字开头 |
MY_INT |
$MY_INT |
只允许使用 _,不允许其他符号 |
another_int |
another int |
不允许空格;必须是一个单词 |
变量名是区分大小写的:my_int、MY_INT、My_Int 和 mY_iNt 是四个不同的变量。在一个程序中使用非常相似的名称更容易导致错误和混淆。
Python 的惯用风格是小写字母加下划线(snake_case)。其他风格是有效的但不常见:
| 惯用风格 | 非惯用风格 | 非惯用的原因 |
|---|---|---|
my_int |
myInt |
camelCase 不是标准 |
int4 |
Int4 |
首字母大写不是标准 |
my_first_string |
myFirstString |
camelCase 不是标准 |
保持一致。如果现有项目使用 camelCase,就遵循该风格。PEP 8 是标准的 Python 风格指南,强调可读性和一致性。
数据类型和 type() 函数
Python 中的变量可以保存不同数据类型的值。常见的内置类型包括 integer、float、string 和 boolean。Python 在赋值时推断类型;无需显式声明。
你可以使用内置的 type() 函数检查任何值或变量的类型:
my_int = 103204934813
my_flt = 45.06
my_string = 'Hello, World!'
my_bool = 5 > 9
print(type(my_int))
print(type(my_flt))
print(type(my_string))
print(type(my_bool))
<class 'int'>
<class 'float'>
<class 'str'>
<class 'bool'>
下表显示了相同的变量及其 type() 结果:
| 变量 | 赋值值 | type() 结果 |
|---|---|---|
my_int |
103204934813 |
<class 'int'> |
my_flt |
45.06 |
<class 'float'> |
my_string |
'Hello, World!' |
<class 'str'> |
my_bool |
5 > 9 (False) |
<class 'bool'> |
变量也可以引用集合。例如,一个变量可以保存一个 list:
my_list = ['item_1', 'item_2', 'item_3', 'item_4']
print(my_list)
print(type(my_list))
['item_1', 'item_2', 'item_3', 'item_4']
<class 'list'>
对于 string 变量,你可以使用 Python 的 string 函数以及索引和切片。使用f-strings 的现代字符串格式化可以直接嵌入变量值:
name = "Sammy"
score = 42
message = f"Player {name} scored {score} points."
print(message)
Player Sammy scored 42 points.
字符串前的 f 前缀允许在大括号中的表达式被求值并插入到字符串中。
重新赋值变量和类型灵活性
Python 变量可以随时重新赋值为新值。同一名称在重新赋值后可以引用不同的值,甚至是不同的类型。
这是动态类型:类型是在赋值时从值推断出来的,而不是从声明中确定的。重新赋值对于接受新值(例如来自用户输入)或在程序运行时更新值很有用,比如每轮增加的分数。
x = 76
print(x)
x = "Sammy"
print(x)
76
Sammy
可变性 vs. 不可变性
重新赋值会改变变量名称所引用的内容。值本身是否可以就地修改,取决于类型是可变的还是不可变的。
不可变类型(例如 int、float、str、tuple)不能就地修改。重新赋值变量会给它一个新值;旧值保持不变。可变类型(例如 list、dict)可以不重新赋值变量就进行就地修改。
以整数(不可变)为例:重新赋值会产生一个新对象。你可以用 id() 来确认这一点:
a = 10
print(id(a))
a = 20
print(id(a))
140704199837472
140704199837792
两个不同的 id 值确认 a 不再引用原始对象;Python 创建了一个持有 20 的新对象。确切数字因系统而异。
以列表(可变)为例:就地修改保持相同的对象。id() 再次显示了区别:
items = ['apple', 'banana']
print(id(items))
items.append('cherry')
print(id(items))
2025123456789
2025123456789
匹配的 id 值确认 append() 修改了现有的列表对象,而不是创建一个新的。
如果你将 items 重新赋值为一个新列表,那么变量将引用那个新列表;旧列表保持不变,如果没有其他引用它,它可能会被丢弃。
多重赋值
你可以在一个语句中将一个值赋给多个变量,或者在一行中将多个值赋给多个变量。
将相同值赋给多个变量:
x = y = z = 0
print(x)
print(y)
print(z)
0
0
0
这种模式在你需要多个计数器、分数或标志时很有用,这些值在循环或计分系统单独更新它们之前都应该从相同值开始。例如,你可能在游戏开始时设置 wins = losses = ties = 0,然后在每轮完成时递增每个变量。
x、y 和 z 都引用整数 0。将多个值赋给多个变量(顺序必须匹配):
j, k, l = "shark", 2.05, 15
print(j)
print(k)
print(l)
shark
2.05
15
j 获取 "shark",k 获取 2.05,l 获取 15。当这能保持代码清晰时使用它;避免为了更少的行数而牺牲可读性。
变量作用域:全局变量和局部变量
变量的scope 是程序中该名称被定义并可访问的部分。在函数外部定义的变量是global(全局变量);在函数内部定义的变量是该函数的local(局部变量)。
为什么这很重要:使用错误的 scope 会导致 NameError,或者读取和更新错误的变量。优先使用局部变量、显式的参数和返回值;过度使用全局变量会使代码更难理解和测试。
glb_var = "global"
def var_function():
lcl_var = "local"
print(lcl_var)
var_function()
print(glb_var)
local
global
函数打印了 local,因为 lcl_var 在函数内部被定义和赋值。它没有打印任何关于 glb_var 的内容,因为 glb_var 在函数体中从未被引用。
glb_var 在模块级别定义,因此在函数内部也是可见的:
glb_var = "global"
def var_function():
lcl_var = "local"
print(lcl_var)
print(glb_var)
var_function()
print(glb_var)
local
global
global
局部变量在函数外部不可见:
glb_var = "global"
def var_function():
lcl_var = "local"
print(lcl_var)
print(lcl_var)
NameError: name 'lcl_var' is not defined
同一个名称可以同时用于全局变量和局部变量。在函数内部,局部名称优先:
num1 = 5
def my_function():
num1 = 10
num2 = 7
print(num1)
print(num2)
my_function()
print(num1)
10
7
5
函数打印了局部 num1(10)和 num2(7)。调用后,print(num1) 打印了全局 num1(5)。
你可以使用 global 语句在函数内部给全局变量赋值:
def new_shark():
global shark
shark = "Sammy"
new_shark()
print(shark)
Sammy
谨慎使用 global。过度依赖它会使控制流和测试变得更困难;传递参数和返回值通常更清晰。如果你只在函数内部读取变量而不赋值,则该变量是全局变量;要使用局部变量,必须在函数体中给它赋值。
一个常见的错误是在函数内部尝试修改全局变量而没有声明它为 global。Python 看到函数内部的赋值,会将该变量视为整个函数体的局部变量,即使在赋值前的行也会如此。这会导致 UnboundLocalError:
counter = 0
def increment():
counter = counter + 1
increment()
UnboundLocalError: local variable 'counter' referenced before assignment
要修改全局变量,请在使用前用 global 语句声明它:
counter = 0
def increment():
global counter
counter = counter + 1
increment()
print(counter)
1
如果没有 global counter,Python 一旦看到赋值 counter = counter + 1,就会将 counter 视为局部变量,这意味着右侧试图读取一个尚未存在的局部变量。
Python 常量
常量是你打算不更改的名称。Python 不强制执行不可变性;约定和可选的类型提示来传达意图。
惯用做法是为常量名称使用 SCREAMING_SNAKE_CASE,并且当你想表示不重新赋值时,使用 typing.Final 注解:
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
# 可选:表示 PI 不应被重新赋值(工具可以检查这一点)
from typing import Final
PI: Final[float] = 3.14159
MAX_RETRIES 和 DEFAULT_TIMEOUT 按约定是常量。PI 被注解为 Final;运行时仍然允许重新赋值,但类型检查器和 linter 可以标记它。使用 SCREAMING_SNAKE_CASE 表示常量有助于读者将其与普通变量区分开来。
Python 变量的常见错误
避免这些错误可以减少 bug 并使代码更容易维护。
大小写敏感: my_var 和 My_Var 是不同的。大写拼写错误会导致 NameError 或使用错误的变量。
count = 5
print(Count)
NameError: name 'Count' is not defined
无意中的重新赋值: 将变量名重复用于不同目的会覆盖原始值,并可能破坏仍期望旧值的逻辑。
total = 100
total = total - 20 # 预期:扣除 20
total = 50 # 意外:覆盖计算后的值
print(total)
50
第三行悄无声息地丢弃了减法的结果,因此程序继续使用 50 而不是预期的 80。这种 bug 不会产生错误,在快速阅读时很难发现。
遮蔽内置名称: 使用像 list、str、dict 或 id 这样的名称作为自己的变量会隐藏内置函数或类型,并可能导致微妙的错误:
list = [1, 2, 3]
other = [4, 5]
combined = list(other)
TypeError: 'list' object is not callable
这里 list 指的是你的列表,而不是内置的 list 构造函数。改用像 my_list 或 items 这样的名称。
实际示例:用户输入和变量
变量的一个常见用途是存储用户输入,然后在输出或计算中使用。input() 函数从用户读取一行并将其作为字符串返回:
name = input("Enter your name: ")
age_str = input("Enter your age: ")
age = int(age_str)
print(f"Hello, {name}. In 10 years you will be {age + 10}.")
示例会话:
Enter your name: Alex
Enter your age: 25
Hello, Alex. In 10 years you will be 35.
name 保存第一个提示的字符串。age_str 保存第二个输入;int(age_str) 将其转换为整数以进行计算。结果使用 f-string 打印。
常见问题解答
如何在 Python 中声明变量?
通过编写变量名、赋值运算符 = 和值(例如 x = 5)来声明变量。不需要类型关键字或单独的声明。赋值执行后变量即存在。
Python 是否要求声明变量类型?
不需要。Python 使用动态类型,并在赋值时从值推断类型。你可以使用内置的 type() 函数检查任何值或变量的类型。
Python 变量可以改变类型吗?
可以。将变量重新赋值为不同类型的价值是允许的。例如,x = 10 后跟 x = "hello" 是有效的;x 先引用整数,然后引用字符串。
Python 中变量命名的规则是什么?
名称必须是一个单词(无空格),仅包含字母、数字和下划线,且不能以数字开头。名称区分大小写。按惯例,使用小写字母加下划线(snake_case)。
Python 中的变量区分大小写吗?
是的。my_var、My_Var 和 MY_VAR 是三个不同的变量。使用错误的大小写如果名称未定义会导致 NameError。
结论
变量是 Python 3 中存储和使用数据的基本构建块。本教程涵盖了声明和重新赋值、命名规则和惯例、数据类型和 type() 函数、作用域、常量以及常见错误。使用变量来保存用户输入、计算结果,以及在函数和 class 之间传递的值。应用一致的命名和作用域选择,以保持代码清晰且易于维护。