W
e
l
c
o
m
e
: )

2.编程基础概念

编程基础概念

本篇导航

本篇讲 Python 最底层的几块地基:程序由模块/语句怎么构成、缩进为什么是语法、注释与文档字符串的区别、
三种格式化输出(% / format / f-string)、input() 输入,以及一切皆对象下的变量与引用模型。
学完能读懂并写出规范的 Python 基础代码。

本篇输出均为本机实跑

环境:Python 3.13.14。原文基于 Python 3.7 的示例值已更新,过时处标注 [!warning] 原文勘误。
验证脚本:verify/py02/run02.py(19 组)。


1 Python 程序的构成

图片5|494

  1. Python 程序由模块组成。一个模块对应一个 Python 源文件,后缀名一般为 .py。
  2. 模块由语句组成。运行 Python 程序时,会按模块中语句的顺序依次执行。
  3. 语句是 Python 程序的构造单元,用于创建对象、变量赋值、调用函数、控制流程等。
补充:模块与语句的关系

一个 .py 文件就是一个模块,模块名就是文件名(不含 .py)。
语句从上往下依次执行——这也是为什么函数/类的定义语句要写在调用语句之前,否则会 NameError。


2 代码的组织和缩进

很多编程语言用字符(如花括号 {})或关键字(如 begin/end)来划分代码块,再配合缩进提升可读性。而「龟叔」设计 Python 时,直接用缩进来组织代码块,并让缩进成为 Python 语法的强制规定。

缩进时用几个空格都可以,但同一份代码中数目必须统一,通常采用四个空格表示一个缩进层次。

同时要避免把 tab 制表符与空格混用。目前常用编辑器一般把 tab 制表符设为 4 个空格。

Python 官方推荐的代码风格是 PEP 8,有兴趣可参考:https://www.python.org/dev/peps/pep-0008/

混用 tab 与空格会直接报错

Python 3 已禁止同一文件中混用 tab 和空格缩进,会抛:

TabError: inconsistent use of tabs and spaces in indentation

解决办法:在编辑器里勾选「用空格代替制表符」(PyCharm:Settings → Editor → Code Style → Python,勾选 Use spaces)。


3 使用注释

为方便阅读,Python 允许在程序中写下说明性文字来提高可读性,这些文字说明就称为注释。

核心作用:

  1. 解释代码的功能、思路与复杂逻辑
  2. 临时屏蔽不需要运行的代码(调试用)
  3. 提升可读性,方便团队协作
  4. 便于后期维护,快速回忆代码用途

3.1 单行注释(最常用)

  • 语法:# 注释内容

  • 作用:注释一行文字,# 后面的所有内容都会被忽略

  • 用法:可以写在代码行末尾,也可以单独占一行

    # 这是单独一行的单行注释,解释下面代码的作用
    print(10) 
    # Python 里的函数,就是底层「打包好、能重复用的代码」:你给它输入,它帮你干活,最后给你结果
    
  • 注释快捷键:ctrl+/

3.2 多行注释

  • 语法:''' 多行注释内容 ''' 或 """ 多行注释内容 """
  • 作用:一次性注释多行文字,适合写长说明、函数功能、文件头部说明
  • 开头三引号必须单独占一行,结尾三引号也必须单独占一行
  • 单三引号 ''' 与双三引号 """ 完全等价,不要混用
  • 适合写长注释;较短的单行说明用 # 更简洁
  • Python 中其实并没有真正的「多行注释」语法,上面这种方式本质是一个字符串字面量。
'''
这是多行注释
可以写很多行文字
用来解释整个文件、函数或复杂逻辑
'''

"""
这也是多行注释
单三引号和双三引号效果完全一样
任选一种,保持统一即可
"""

# 输出内容
print(100)  # 输出:100
实跑输出
100

上面两组三引号字符串被当作表达式语句执行后直接丢弃,所以看起来"像注释",但解释器确实创建了两个 str 对象。

原文这句说得对,值得展开

原文第 6 条「Python 中其实并没有真正的多行注释语法……本质是一个字符串字面量」——这是正确的,而且是很多教程讲错的点。

实测验证:

s = """
这是一段三引号字符串
"""
print(type(s).__name__)   # str
str

它与 # 的本质区别:

对比项 # 单行注释 三引号字符串
是否产生对象 否,解释器直接忽略 是,产生 str 对象
能否赋值 不能 能
运行期开销 无 有
何时成为文档 否 仅位于模块/函数/类首行时写入 __doc__

实践建议:批量注释多行代码请用编辑器的 ctrl+/;三引号留给文档字符串(docstring)。

3.3 文件编码声明注释(特殊的单行注释)

在文件开头加上中文声明注释,用以指定源码文件的编码格式。

  • 格式示例:# coding:utf-8
  • 这个注释在 Python 2 时代是必须写的,但在 Python 3 中通常可以省略。
# coding:utf-8 
print("你好,Python")
实跑输出
你好,Python
为什么 Python 3 不用写了

Python 3 源码默认就是 UTF-8(见 PEP 3120),所以写不写都一样。
只有当你用了非 UTF-8 编码(如 GBK)保存源码时才需要显式声明。

3.4 文档字符串(Docstring)(特殊的多行注释)

这是 Python 的特色注释,专门给函数、类、模块写说明。Docstring 本质虽是字符串,但 Python 给了它「特权」——把它存进对象的 __doc__ 属性。因此它不只写给人看,也写给机器(如 IDE、文档生成工具)看。(可被调用:Python 解释器会将其保存为对象的 __doc__ 属性,可通过代码读取,或用 help() 函数查看。)

  • 语法:定义函数/类后,第一行写 """ 文档说明 """
  • 作用:标准化地说明函数功能、参数、返回值、异常
def add(x, y):
    """
    两个数字相加(文档字符串,必须写在函数第一行)
    参数:
        x: 第一个数字(int/float)
        y: 第二个数字(int/float)
    返回:
        两个数的和
    """
    return x + y

# 查看文档注释(运行代码可输出)
help(add)
实跑:help(add) 的真实输出
Help on function add in module __main__:

add(x, y)
    两个数字相加(文档字符串,必须写在函数第一行)
    参数:
        x: 第一个数字(int/float)
        y: 第二个数字(int/float)
    返回:
        两个数的和

也可以直接用 add.__doc__ 取到同一段文字——这就是它与普通三引号字符串的关键区别。


4 使用 \ 行连接符

一行程序的长度本身没有限制,但为了可读性更强,通常会把它拆成多行。这时可以用 \(行连接符),把它放在行尾,Python 解释器仍会将其视为同一行。

>>> a = [10,20,30,40,\
         50,60,70,\
         80,90,100]
>>> a
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> a = 'abcdefghijklmnopqrstuvwxyz'
>>> b = 'abcdefg\
		hijklmn\
		opqrst\
		uvwxyz'
>>> a
'abcdefghijklmnopqrstuvwxyz'
>>> b
'abcdefghijklmnopqrstuvwxyz'
上面这段代码里的 >>> 是提示符,不是代码

>>> 是交互式解释器的提示符,直接粘进 .py 文件会 SyntaxError。写成脚本文件要去掉:

a = [10, 20, 30, 40, \
     50, 60, 70, \
     80, 90, 100]
print(a)
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

注意第二个例子 b 的写法其实有坑:续行时行首的 tab/空格会被算进字符串,
所以 b 实际会是 'abcdefg\t\thijklmn\t\topqrst\t\tuvwxyz'(含制表符),
并不等于 a。原文把它俩并列容易误导。真要拼接长字符串,推荐用括号隐式续行:

b = ('abcdefg'
     'hijklmn'
     'opqrst'
     'uvwxyz')
print(b == 'abcdefghijklmnopqrstuvwxyz')
True
更推荐的续行方式:括号

在 ()、[]、{} 内部换行不需要 \,Python 会自动续行。这是 PEP 8 推荐的做法,比 \ 更不容易出错。


5 Python 中的格式化输出

5.1 格式化输出

目前为止,我们的输出都是直接通过 print(变量名称) 打印的。但实际工作中,往往需要对输出做格式化处理(按指定格式输出)。

5.2 百分号格式化输出

基本语法:

# 伪代码:演示三种调用形态
print(变量名称)
print('字符串%格式' % (变量名称))
print('字符串%格式 %格式 %格式' % (变量名称1, 变量名称2, 变量名称3))

% 格式常见形式如下:

格式符号 转换
%s 字符串
%d 有符号的十进制整数
%f 浮点数,默认保留小数点后 6 位
%c 字符
%u 无符号十进制整数
%o 八进制整数
%x 十六进制整数(小写,前缀用 0x)
%X 十六进制整数(大写,前缀用 0X)
%e 科学计数法(小写 e)
%E 科学计数法(大写 E)
%g %f 和 %e 的简写
%G %f 和 %E 的简写
原文勘误(两处)
  1. 原文在案例注释里写「%f 默认输出 5 位小数」,但实测:

    print('%f' % 3.5)
    3.500000

    默认是 6 位(与原文表格中「默认保留小数点后 6 位」一致,是注释写错了)。

  2. 原文表格中 %x / %X 的描述写作「十六进制整数(小写 ox)」——ox 是字母 o,
    正确应为数字 0 加 x,即 0x。实测:

    '%x' % 255 -> ff
    '%X' % 255 -> FF

案例:定义两个变量 name='小龙女'、age=18,按如下格式输出:我的名字是小龙女,今年 18 岁了。

name = '小龙女'
age = 18

# 格式化输出:我的名字是小龙女,今年18岁了
print('我的名字是%s,今年%d岁了' % (name, age))
实跑输出
我的名字是小龙女,今年18岁了

Snipaste_2022-06-16_13-22-48

案例:定义两个变量 title = '大白菜'、price = 3.5,按如下格式输出:今天蔬菜特价了,大白菜只要 3.5 元/斤。

title = '大白菜'
price = 3.5

# 格式化输出:今天蔬菜特价了,大白菜只要3.5元/斤
# %f 默认输出 6 位小数(已修正原文的「5 位」)
print('今天蔬菜特价了,%s只要 %f 元/斤' % (title, price))
print('今天蔬菜特价了,%s只要 %.1f 元/斤' % (title, price))
实跑输出
今天蔬菜特价了,大白菜只要 3.500000 元/斤
今天蔬菜特价了,大白菜只要 3.5 元/斤

其实除了 %f 可以设置小数位数以外,%d 也可以填充序号。

案例:定义两个变量 id = 1、name = '小龙女',按如下格式输出:姓名:小龙女,学号:000001

id = 1
name = '小龙女'

print("姓名:%s,学号:%d" % (name, id))
print("姓名:%s,学号:%06d" % (name, id))
实跑输出
姓名:小龙女,学号:1
姓名:小龙女,学号:000001

%06d 含义:宽度 6,不足部分用 0 左填充。

5.3 format 方法格式化输出

关于原文此处的外链

原文在此处附了一个 format.md 的链接,但该笔记在本库中并不存在(已确认为断链),故本篇移除该链接。

基本语法:

print('字符串{}'.format(变量名称1))
# 字符串有几个大括号,format 中就写几个变量,变量按顺序排布
print('{}字符串{}'.format(变量名称1, 变量名称2))
# 设置指定位置
print('{1}字符串{0}'.format(变量名称1, 变量名称2))

案例:定义两个变量 name = '小龙女'、mobile = '18530908789',按以下格式输出:姓名:小龙女,联系方式:18530908789

name = '小龙女'
mobile = '18530908789'
# 姓名小龙女,电话18530908789
print('姓名{},电话{}'.format(name, mobile))

name = '小龙女'
mobile = '18530908789'
# 姓名小龙女,电话18530908789
print('姓名{1},电话{0}'.format(mobile, name))
实跑输出
姓名小龙女,电话18530908789
姓名小龙女,电话18530908789

注意第二行为什么结果一样:'姓名{1},电话{0}' 中 {1} 取的是 format() 的第 2 个参数 name,
{0} 取的是第 1 个参数 mobile。所以虽然传参顺序变了,但通过下标把它"换"回来了。
这正是位置索引的用途——同一个变量可以在字符串里出现多次。

Snipaste_2022-06-17_22-26-05

5.4 format 方法简写形式格式化输出(推荐)

在 Python 3.6 以后版本,为了简化 format 输出操作,引入了一个简写形式:

name = '小龙女'
mobile = '18530908789'

print(f"姓名:{name},联系方式:{mobile}")
实跑输出
姓名:小龙女,联系方式:18530908789

三种格式化方式怎么选
方式 引入版本 推荐度 说明
% 最早 一般 老代码常见,类型多时易错
str.format() 2.6 良好 功能全,支持位置/命名/格式规范
f-string 3.6 首选 可读性最好、最快,可直接内嵌表达式

f-string 还能直接写表达式,例如 print(f"{age + 1}")、print(f"{name.upper()}")。

5.5 填充与对齐

填充常与对齐配合使用。

^、<、> 分别表示居中、左对齐、右对齐,其后跟宽度。

: 后面可带填充字符,只能是单个字符;不指定时默认用空格填充。

name = '小龙女'

# 左对齐
print('我叫{:<8}。'.format(name))
print(f'我叫{name:!<8}。')
# 居中对齐
print('我叫{:^8}。'.format(name))
print(f"我叫{name:!^8}。")
# 右对齐
print('我叫{:>8}。'.format(name))
print(f"我叫{name:!>8}。")
实跑输出(注意空格与 ! 的填充差异)
我叫小龙女     。
我叫小龙女!!!!!。
我叫  小龙女   。
我叫!!小龙女!!!。
我叫     小龙女。
我叫!!!!!小龙女。

宽度 8 是包含内容本身的总宽度;小龙女 占 3 个字符,所以补 5 个填充符。

5.6 数字格式化

浮点数通过 f,整数通过 d 进行需要的格式化。

name = "小龙女"
price = 3888.234342
age = 18
salary = 18.5

print(f"我是{name},我的存款有{price:.2f}元。")
print(f'我是{name}, 年龄是{age}, 工资是{salary:!>8.2f}k。')
实跑输出
我是小龙女,我的存款有3888.23元。
我是小龙女, 年龄是18, 工资是!!!18.50k。

其他格式供参考(下表已逐行实跑验证):

数字 格式 输出 描述
3.1415926 {:.2f} 3.14 保留小数点后两位
3.1415926 {:+.2f} +3.14 带符号保留小数点后两位
2.71828 {:.0f} 3 不带小数
5 {:0>2d} 05 数字补零(填充左边,宽度为 2)
5 {:x<4d} 5xxx 数字补 x(填充右边,宽度为 4)
10 {:x<4d} 10xx 数字补 x(填充右边,宽度为 4)
1000000 {:,} 1,000,000 以逗号分隔的数字格式
0.25 {:.2%} 25.00% 百分比格式
1000000000 {:.2e} 1.00e+09 指数记法
13 {:!>5d} !!!13 右对齐(宽度为 5)
13 {:!<5d} 13!!! 左对齐(宽度为 5)
13 {:!^5d} !13!! 中间对齐(宽度为 5)
原文勘误:{:.2e} 的输出大小写

原文表格中 {:.2e} 的输出写作 1.00E+09(大写 E),实测:

{:.2e} -> 1.00e+09     小写 e
{:.2E} -> 1.00E+09     大写 E(才对应原文写法)

小写 e 配 {:.2e},大写 E 要写成 {:.2E}。这与 %e / %E 的规则一致。

不写填充字符时默认用空格

原文表格里"右对齐(宽度为 5)"用的是 {:5d}(无填充符),实测输出 ' 13'(左侧补空格)。
上表统一改用 {:!>5d} 的写法,填充效果更直观。

5.7 格式化输出中的转义符号

可以用 \ + 特殊字符 实现某些难以直接表示的效果,例如换行。

常见转义字符如下:

转义字符 描述
\(在行尾时) 续行符
\\ 反斜杠符号
\' 单引号
\" 双引号
\b 退格 (Backspace)
\n 换行
\t 横向制表符
\r 回车

在字符串中,若出现 \t 和 \n,它们分别代表对应的转义字符。

说明(原文此处把说明文字放进了 ```python 代码块,实为非代码)
  • \t:制表符,一个 tab 键(4 个空格)的距离
  • \n:换行符

案例:

print('*\t*\t*')
print('hello\nworld')
实跑输出
*	*	*
hello
world

特别说明

默认情况下,每个 print() 执行完毕后都会输出一个 \n 换行符。若不想换行,可以给 print() 添加一个 end 参数。

print('*', end='')

案例:

# 不带 end 参数默认输出换行
print('*')
print('*')

# 带 end 参数输出 end 参数中的内容
print('*', end='')
print('*', end='我是第二个print的结尾')
实跑输出
*
*
**我是第二个print的结尾

前两个 print 各自换行;后两个因为指定了 end,输出被拼在了同一行。


6 Python 中的标准输入

6.1 为什么需要输入

到目前为止,我们的程序都只能把数据输出给用户。但实际工作中,经常需要获取用户的输入信息,例如银行系统中的密码输入、淘宝中的用户登录验证。

image-20210306182224429

6.2 input() 输入方法

在 Python 中,若想让 Python 程序接受用户的输入信息,可以使用 input() 方法。

基本语法:

input()

但单独一个 input() 意义不大,通常还要用一个变量临时接收用户输入,以便后续操作。

变量名称 = input('提示信息:')

案例:银行系统中输入密码的过程:

passwd = input("请输入您的银行卡密码:")

print(f'您输入的银行卡密码为:{passwd}')
实跑输出(模拟输入 123456)
请输入您的银行卡密码:您输入的银行卡密码为:123456

因为 input() 会等待键盘输入,自动实跑时用模拟输入代替了手工输入。

6.3 input() 方法重要事项

记住:所有由 input() 方法获取的数据都是字符串类型。

name = input('请输入您的姓名:')
age = input('请输入您的年龄:')

print(f"姓名:{name},类型:{type(name)}")  # <class 'str'>
print(f"年龄:{age},类型:{type(age)}")  # <class 'str'>
实跑输出(模拟依次输入 小龙女、18)
请输入您的姓名:请输入您的年龄:姓名:小龙女,类型:<class 'str'>
年龄:18,类型:<class 'str'>

最常见的坑:input() 拿到的是字符串

即使你输入的是数字 18,age 的类型也是 str。直接做数值运算会出问题:

age = input('年龄:')      # 输入 18
print(age + 1)            # ❌ TypeError
TypeError: can only concatenate str (not "int") to str

正确写法是先转换类型:

age = int(input('年龄:'))
print(age + 1)            # ✅ 19

若担心用户乱输入导致 ValueError,用 try/except 兜底。


7 对象

Python 中,一切皆对象。

每个对象由三部分组成:标识(identity)、类型(type)、值(value)。

  1. 标识用于唯一标识对象,通常对应对象在计算机内存中的地址。用内置函数 id(obj) 可返回对象 obj 的标识。
  2. 类型表示对象所存「数据」的类型,它限制了对象的取值范围以及可执行的操作。可用 type(obj) 获得对象的类型。
  3. 值表示对象中所存储的数据信息,用 print(obj) 可直接打印出值。

对象本质上是:一个内存块,拥有特定的值,支持特定类型的相关操作。

>>> a = 3
>>> a
3
>>> id(3)
1531372336
>>> type(3)
<class 'int'>
>>> b = "我爱你"
>>> id(a)
1531372336
>>> type(a)
<class 'int'>
>>> print(a)
3
>>> id(b)
46806816
>>> type(b)
<class 'str'>
实跑输出(本机,id 值与原文不同是正常的)
a = 3
id(3)   = 140734848902120
type(3) = <class 'int'>
id(a)   = 140734848902120   (与 id(3) 相同,小整数缓存)
type(a) = <class 'int'>
id(b)   = 1779096912960
type(b) = <class 'str'>
关于 id() 的值

原文示例中的 1531372336、46806816 是 Python 3.7 + 特定机器下的值。
id() 每次运行都可能不同,不要把它当固定值记忆或写死在代码里。

但有一个恒定规律值得记:CPython 对 -5 ~ 256 的小整数做了缓存,
所以 a = 3 后 id(a) == id(3) 恒成立——这正是原文示例想说明的点。

图片6


8 引用

在 Python 中,变量也叫对象的引用——因为变量存储的是对象的地址,通过地址「引用」了对象。

  • 变量位于:栈内存(压栈、出栈等细节后续再讲)。
  • 对象位于:堆内存。

图片7

Python 是动态类型语言

变量不需要显式声明类型。根据变量引用的对象,Python 解释器自动确定数据类型。

Python 是强类型语言

每个对象都有数据类型,只支持该类型支持的操作。

动态类型 ≠ 弱类型(常被混淆)
  • 动态类型:变量的类型由运行时绑定的对象决定,同一个变量可以先后指向不同类型的对象。
  • 强类型:类型之间不会隐式乱转。'18' + 1 会报 TypeError,不像某些弱类型语言会自动转成 19。

这两个维度是独立的:Python 是 动态 + 强类型;JavaScript 是 动态 + 弱类型。

关于「变量在栈、对象在堆」的说法

这是 CPython 实现的简化模型,用来帮助理解是可以的。
严格说 CPython 的局部变量名存在栈帧的 localsplus 数组里,对象在由 pymalloc 管理的堆上,
并非教科书式的栈/堆二分。入门阶段按原文理解即可,深入时再纠正。


9 变量

9.1 什么是变量

什么是「量」:量是程序中的最小单元。

那什么是变量呢?

变量用来记录程序中的数据。它本质上代表一个「可操作的存储空间」——空间位置是确定的,但里面放什么值并不确定。我们通过变量名访问「对应的存储空间」,从而操纵其中存储的值。

  1. 变量是存储数据的容器
  2. 变量是在程序运行过程中可以发生改变的量
  3. 变量存储的数据是临时的

9.2 标识符

什么是标识符

标识符是程序员编写 Python 代码时自定义的名称,专门用于给变量、函数、类、模块、常量、包等程序元素命名,以唯一标识一个程序对象,方便调用和区分。

简单说:你自己起的所有名字(变量名、函数名、类名等)都是标识符。

标识符:用于变量、函数、类、模块等的名称。

标识符定义规则

标识符有如下特定规则:

  1. 组成部分:数字、字母、下划线 _
  2. 不可以:以数字开头;使用 Python 关键字;包含空格
  3. 见名知意:提升可读性
  4. 大小写敏感:a 与 A 不同
  5. 命名方式:蛇形命名(下划线命名)
  6. 变量名、函数名、方法名推荐:小写 + 下划线,如 user_name、get_student_info()
  7. 类名推荐:大驼峰(每个单词首字母大写),如 class Student
  8. 常量推荐:全大写 + 下划线,如 MAX_COUNT = 100
  9. 长度无限制,但不建议太长:名字过长会严重影响代码阅读与维护,行业惯例一般控制在 2~3 个单词、不超过 30 字符。

注意:以双下划线开头和结尾的名称通常有特殊含义,应尽量避免这种写法。例如 __init__ 是类的构造函数。

可以用的标识符(合法):

name 
age1 
user_name 
my_var 
Student 
_private 
MAX_COUNT

不可以用的标识符(非法):

1name        # 数字开头 
user-name    # 有减号 
if           # 关键字 
class        # 关键字 
user name    # 有空格 
a@b          # 有特殊符号 
$money       # Python 不允许 $
上面两段是「名字清单」,不是可执行代码

原文把它们放在 ``python 代码块里,但直接运行会 SyntaxError/NameError。 合法清单只是名字罗列;非法清单每一行都会报错(如 1name触发SyntaxError: invalid decimal literal`)。

关键字

关键字:被 Python 语言赋予特殊含义、用于专门用途的单词。

用 Python 帮助系统查看关键字:

help('keywords')
实跑输出(Python 3.13,共 35 个)
False       None        True        and         as          assert
async       await       break       class       continue    def
del         elif        else        except      finally     for
from        global      if          import      in          is
lambda      nonlocal    not         or          pass        raise
return      try         while       with        yield

注意

无需刻意背关键字,后面都会学到。

补充:还有一类「软关键字」

除了上面 35 个硬关键字,Python 3.10+ / 3.12+ 引入了软关键字(soft keywords):

['_', 'case', 'match', 'type']

它们只在特定语法上下文中才被当作关键字,其他场合仍可作普通标识符使用。
例如 match 是 match 语句的关键字,但你依然可以写 match = 5(不推荐,但合法)。

用 keyword.kwlist / keyword.softkwlist 可以分别查看:

import keyword
print(len(keyword.kwlist), keyword.softkwlist)
35 ['_', 'case', 'match', 'type']

推荐命名规则

这些规则不做语法强制,但推荐在编程中遵守。开发中通常约定俗成地遵循如下规则:

类型 规则 例子
模块和包名 全小写字母,尽量简单;多个单词之间用下划线。 math,os,sys
函数名 全小写字母,多个单词之间用下划线隔开。 phone,my_name
类名 首字母大写,采用大驼峰原则;多个单词时,每个单词首字母大写、其余小写。 MyPhone、MyClass、Phone
常量名 全大写字母,多个单词用下划线隔开。 SPEED、MAX_SPEED
总结

类名为大驼峰;常量名全大写,多个单词用下划线分割;其余全是蛇形命名法。

9.3 变量的定义

变量的声明和赋值,用于将一个变量绑定到一个对象上,格式:变量名 = 表达式。

说明
  • = 叫作赋值运算符
  • 作用:把右边的值装进左边的变量里
  • 等号两边各保留一个空格(PEP 8 规范,Python 中建议符号两侧都留空格)

最简单的表达式就是声明变量,例如 a = 123。运行时,解释器先运行右边的表达式,生成一个代表运算结果的对象,再把这个对象的地址赋值给左边的变量。

变量在使用前必须先初始化(先赋值)

my_name
实跑报错
NameError: name 'my_name' is not defined

变量 my_name 使用前未赋值,因此报错:'my_name' is not defined。

9.4 删除变量和垃圾回收机制

可以用 del 关键字删除不再使用的变量。

a = 123
del a
a
实跑报错
NameError: name 'a' is not defined

若一个对象没有任何变量引用(引用数为 0),就会被垃圾回收器回收,以释放内存空间。

del 删的是「名字」,不是「对象」

del a 只是把名字 a 从当前命名空间移除,并让对象的引用计数 -1。
只有当引用计数降到 0 时,对象才会被销毁:

a = [1, 2, 3]
b = a          # 现在 [1,2,3] 被 a 和 b 两个名字引用
del a          # 只删了名字 a,对象还在(b 还指着它)
print(b)       # [1, 2, 3]  ← 对象没被回收

这就是为什么 del 之后对象不一定立即消失。

9.5 链式赋值

链式赋值用于把同一个对象赋给多个变量。

x = y = 123

等价于:

x = 123
y = 123
实跑验证
x=123, y=123, id 相同: True

两个名字指向同一个对象(对于小整数 123,还叠加了整数缓存的效果)。

9.6 系列解包赋值

把系列数据赋给数量相同的变量(个数必须一致)。

a, b, c = 4, 5, 6

等价于:

a = 4
b = 5
c = 6

用系列解包赋值实现变量交换:

a, b = 1, 2
a, b = b, a
print(a, b)
实跑输出
2 1

无需临时变量即可完成交换——这是 Python 的招牌写法。
原理:右边的 b, a 先被打包成一个元组,再按顺序解包赋给左边的 a, b。

个数不一致会报 ValueError: too many values to unpack。

9.7 变量的内存示意图

变量 vs 宾馆:

9.8 变量的内存分析

变量由三部分组成:

  • 标识:表示对象所存储的内存地址,用内置函数 id(obj) 获取
  • 类型:表示对象的数据类型,用内置函数 type(obj) 获取
  • 值:表示对象所存储的具体数据,用 print(obj) 打印输出

name = '马丽亚'
print(name)
print('标识,',id(name))  # 变量 name 所指向的对象在内存中的唯一地址编号(内存地址)
print('类型,',type(name))
print('值,',name)
实跑输出
马丽亚
标识, 1779096913200
类型, <class 'str'>
值, 马丽亚

当多次赋值之后,变量名会指向新的空间。


10 常量

10.1 常量

Python 不支持常量,即没有语法规则限制改变常量的值。我们只能约定常量的命名规则,并在逻辑上不对其值作修改。

常量命名规则:全字母大写,多个单词之间用下划线连接。

MAX_SPEED = 120

print(MAX_SPEED)

MAX_SPEED = 140  # 实际是可以改的。只能逻辑上不做修改。

print(MAX_SPEED)
实跑输出
120
140

确实改掉了——所谓常量只是命名约定,解释器并不阻止。

真想防改动怎么办

若希望「改了就报错」,有几种办法:

  • 用 typing.Final(只给类型检查器看,运行时不拦):

    from typing import Final
    MAX_SPEED: Final = 120
  • 用 @property 只给 getter、不给 setter

  • 用 enum.Enum 定义枚举

  • 用 dataclasses 的 frozen=True

Python 的哲学是「我们相信你是成年人」(we are all consenting adults),所以默认不设防。


11 术语表(重要英文单词)

11.1 语法与结构

术语 全拼 / 说明 释义
module — 模块,一个 .py 源文件即一个模块
statement — 语句,Python 程序的最小构造单元
indentation — 缩进,Python 用它划分代码块,属语法强制
PEP Python Enhancement Proposal Python 增强提案;PEP 8 是官方代码风格规范
identifier — 标识符,程序员自定义的变量/函数/类/模块等名称
keyword — 关键字,被语言赋予特殊含义、不可作标识符的单词
soft keyword — 软关键字,仅在特定语法上下文中保留(match/case/type/_)
docstring Document String 文档字符串,模块/函数/类首行的三引号字符串,存于 __doc__
Snake Case — 蛇形命名,小写 + 下划线,如 user_name
Camel Case — 驼峰命名,类名用大驼峰,如 MyClass
escape character — 转义字符,以 \ 开头表示特殊字符,如 \n、\t

11.2 对象与变量

术语 全拼 / 说明 释义
identity — 标识,对象的唯一身份,用 id(obj) 获取(通常即内存地址)
type — 类型,决定对象的取值范围与可执行操作,用 type(obj) 获取
value — 值,对象中存储的数据
reference — 引用,Python 变量本质是对象的引用(存地址)
stack / heap — 栈 / 堆;简化模型中变量在栈、对象在堆
dynamic typing — 动态类型,变量类型由运行时绑定的对象决定
strong typing — 强类型,类型间不随意隐式转换
garbage collection — 垃圾回收,引用计数归零后自动回收对象内存
chained assignment — 链式赋值,x = y = 123
unpacking — 解包赋值,a, b, c = 4, 5, 6
NameError — 使用未定义名字时抛出的异常

11.3 格式化

术语 全拼 / 说明 释义
f-string Formatted String Literal 格式化字符串字面量,Python 3.6+,前缀 f,首选格式化方式
format spec Format Specification 格式规范迷你语言,如 :.2f、:>8、:,,在 {} 内用 : 引出
%-formatting — 百分号格式化,最老的格式化方式
stdin / stdout Standard Input / Output 标准输入 / 输出;input() 读 stdin,print() 写 stdout

12 系列导航

01_Python基础
  1. 1.Python 入门
  2. 2.编程基础概念
  3. 3.Python 中的基础数据类型
  4. 4.字符串
  5. 5.内建数据结构
  6. 6.控制语句
  7. 7.函数用法
  8. 8.面向对象编程
  9. 9.异常和错误
  10. 10.文件操作(IO 技术)
  11. 11.模块 (module)
  12. 12.正则表达式 ★★★
  13. 13.并发编程
  14. 14.网络编程
  15. 15.Python操作MySQL
相关主题
  • 字符串方法进阶:4.字符串
  • 面向对象深化(元类、单例):5.Python面向对象进阶
  • 格式化相关的练习:1.分支和循环结构实战、2.函数应用实战

13 参考链接

分类:Python

posted @ 2026-04-11 01:51  挖掘鱼  阅读(21)  评论(0)    收藏  举报