说实话,Python基础语法就那么点东西,但很多细节稍不留神就容易出错。今天我们就顺着这份笔记的脉络,挑出几个高频使用但极易踩坑的细节,结合真实场景重新梳理一遍。读完你可能会发现:原来一直用的
sort()居然会修改原列表?
replace()竟然不生效?
*args和
**kwargs到底怎么优雅传参?

---
## 一、注释:除了“解释代码”,还能做文档
笔记里简单写了三种形式:
```python
# 单行注释
"""
多行注释(三双引号)
'''
多行注释(三单引号)
'''
```
**必须说清楚**:
"""和
'''本质上是**字符串字面量**,只是当它们孤立存在、不被赋值或操作时,解释器会忽略它们,起到了“注释”的效果。但如果你这样写:
```python
x = """我是字符串"""
```
那它就不是注释了。
**实用场景**:函数内部的文档字符串(docstring)通常用
"""包裹,
help()能读取它:
```python
def add(a, b):
"""返回两个数的和"""
return a + b
help(add) # 会显示 """返回两个数的和"""
```
**踩坑提醒**:如果你用
"""注释掉一大段代码,而这段代码本身又包含
""",会触发
SyntaxError。此时要么改用
#逐行注释,要么用编辑器快捷键批量加
#。
---
## 二、数据类型:一张表理清 Python 内置九大类
笔记列出了:整数、浮点数、字符串、布尔值、列表、元组、字典、集合、
None。
| 类型 | 例子 | 是否可变 | 是否有序 |
|------|------|----------|----------|
| 整数 |
10 | 不可变 | - |
| 浮点数 |
3.14 | 不可变 | - |
| 字符串 |
'hello' | 不可变 | 有序(索引) |
| 布尔值 |
True /
False | 不可变 | - |
| 列表 |
[1,2,3] | **可变** | 有序 |
| 元组 |
(1,2,3) | **不可变** | 有序 |
| 字典 |
{'name':'lgl','age':18} | **可变** | 有序(3.7+) |
| 集合 |
{1,2,3} | 可变 | **无序** |
| None |
None | 不可变 | - |
**重点**:元组的“不可变”是指**元素的指向不可变**,但如果元组内包含列表,列表内容可以变:
```python
t = (1, [2,3])
t[1].append(4) # 合法,t 变成 (1, [2,3,4])
```
但你不能
t[0] = 5,这会报错。
None常被用作“空值”占位,比如函数默认返回值就是
None。判断时推荐
if x is None而非
if not x,因为后者会把
0、
[]等也判为 True。
---
## 三、输出与输入:那些你可能没玩过的花样
### 1.
print()的进阶用法
```python
print(100) # 直接输出值
print('hello world') # 输出字符串
a = 10
print(f'a={a}') # f-string,推荐!清晰高效
```
笔记还提到
t(制表符)、
n(换行)和
end=''。实际项目里,
end常用来构建动态刷新效果:
```python
import time
for i in range(101):
print(f'r进度:{i}%', end='', flush=True)
time.sleep(0.05)
print() # 换行
```
r让光标回到行首,
end=''阻止自动换行,
flush=True强制立即输出——这样你就看到一行进度条在变化。
### 2.
input()的“类型陷阱”
```python
a = int(input('请输入一个整数:'))
```
这样写没问题,但若用户输入
'abc'会抛出
ValueError。**实战中务必加异常处理**:
```python
try:
a = int(input('请输入整数:'))
except ValueError:
print('这不是整数,请重试')
```
另外,
input()返回的一律是字符串,别忘转型。
---
## 四、随机数:别再死记硬背了
```python
import random
print(random.randint(1, 100)) # 闭区间 [1,100],包含两端
print(random.uniform(1, 100)) # 浮点数,范围 [1,100]?实际是闭区间
```
**注意**:
random.uniform(a,b)的端点取决于
a和
b的大小关系,但返回的是
a <= N <= b(若a<=b)或
b <= N <= a,总之是**闭区间**。笔记说“不包含1和100”是错误的——实际上
uniform是包含两端(理论上浮点数精度可能碰巧等于端点,但概率极低)。大家使用时以官方文档为准。
更常用的随机选择:
random.choice(['红','蓝','绿'])、
random.shuffle(list)等,这些笔记没提,但实战频繁。
---
## 五、运算符与布尔逻辑:短路效应是关键
```python
print(2 ** 3) # 8,指数运算
a = False
b = not a # True
c = a and b # False
d = a or b # True
```
and和
or返回的**不是布尔值**,而是**最后一个被求值的操作数**:
```python
print(0 and 10) # 0,因为 0 为假,短路返回 0
print(3 or 0) # 3,因为 3 为真,短路返回 3
```
这个特性常用于简化逻辑,比如
x = y or '默认值',但小心
y=0时也会被当成假。
字符串拼接:
```python
c = 'Hello' + ' ' + 'World' # 用 +
c = 'Ha' * 3 # 'HaHaHa'
```
*可以快速重复字符串,但**不要用
+在循环里拼接大量字符串**,因为字符串不可变,每次
+都会创建新对象,效率极低。推荐用
''.join(list_of_str)。
---
## 六、控制流:
if、
elif与
for的细节
```python
if condition:
# 缩进 4 个空格
elif other:
# ...
else:
# ...
```
**缩进是 Python 的灵魂**,混用 Tab 和空格会报错,现代编辑器都能自动转空格。
for循环笔记里写了
range(10)表示 0~9,
range(1,10)表示 1~9。
range是惰性序列,节省内存,常与
list()搭配转成列表。
但
for循环可以直接迭代字符串、列表、元组、字典、集合:
```python
for ch in 'hello':
print(ch) # 迭代字符
for key in d:
print(key, d[key]) # 迭代字典键
for value in d.values():
print(value) # 迭代值
for k, v in d.items():
print(k, v) # 同时迭代键值对
```
---
## 七、字符串操作:不可变,别忘赋值
笔记里写了切片、
replace、
split、
join。
```python
s = 'hello world'
print(s[0]) # 'h'
print(s[1:5]) # 'ello'(左闭右开)
print(s[1:5:2]) # 'el'(步长2)
new_s = s.replace('l', 'L') # 返回新字符串 'heLLo worLd'
print(s) # 原字符串不变!
parts = s.split(' ') # ['hello', 'world']
joined = ' '.join(parts) # 'hello world'
```
**金句**:字符串是“钢铁直男”——任何操作都生成新对象,绝不改变自己。永远记得把结果赋值回去。
**实战场景**:清洗文本时,常用
strip()去首尾空白,
replace去除换行符,
split按分隔符切分 CSV 数据。
---
## 八、列表:增删改查,排序有坑
```python
lst = [1,2,3]
lst.append(4) # 末尾追加
lst.insert(1, 99) # 在下标 1 前插入 99 -> [1,99,2,3,4]
lst.pop(2) # 删除下标 2 的元素并返回
lst.remove(99) # 删除第一个值为 99 的元素
lst.clear() # 清空
```
**排序的陷阱**:
```python
lst = [3,1,2]
lst.sort() # 修改原列表,返回 None
# 如果想保留原列表,用 sorted()
new_lst = sorted(lst) # 返回新列表
```
排序支持
key和
reverse,比如按字符串长度排序:
```python
words = ['apple', 'pie', 'banana']
words.sort(key=len, reverse=True)
```
**取下标**:
lst[0]获取第一项,
lst[-1]获取最后一项。如果下标越界会报
IndexError,安全方式是用
try或先判断长度。
---
## 九、元组:不可变的“列表”,用在哪?
```python
t = (1, 2, 3)
# t[0] = 100 # 报错
```
元组不可变,因此哈希可计算,可作为字典的键(而列表不行)。另外,函数返回多个值时,本质就是元组:
```python
def get_stats():
return 1, 2, 3 # 自动打包为元组
x, y, z = get_stats() # 解包
```
**注意**:单元素元组必须加逗号
(1,),否则被当作整数。
---
## 十、集合:去重利器,但别指望顺序
```python
s = {1,2,3,3} # 自动去重 -> {1,2,3}
s.add(4)
s.remove(2)
# 集合支持交集、并集等
a = {1,2,3}
b = {2,3,4}
print(a & b) # {2,3}
print(a | b) # {1,2,3,4}
```
集合无序,因此不能通过下标访问。如果需要有序去重,用
dict.fromkeys()或
sorted(set(lst))。
---
## 十一、字典:键值对的“瑞士军刀”
```python
d = {'name': 'lgl', 'age': 18}
print(d.keys()) # dict_keys(['name','age'])
print(d.values()) # dict_values(['lgl',18])
print(d.items()) # dict_items([('name','lgl'), ('age',18)])
del d['age'] # 删除键值对
d.clear() # 清空字典
```
**迭代时删除**会导致运行时错误,安全做法:
```python
for key in list(d.keys()):
if key == 'age':
del d[key]
```
或者用字典推导式创建新字典:
```python
d = {k:v for k,v in d.items() if k != 'age'}
```
**默认值**:
d.get('gender', '未知')如果键不存在返回默认值,不报错。
---
## 十二、函数:定义、参数、作用域
```python
def func(p1, p2, p3):
# 函数体
return 结果
pass # 占位,什么都不做
```
**全局变量**:在函数内修改全局变量需
global声明:
```python
x = 10
def change():
global x
x = 20
change()
print(x) # 20
```
但滥用全局变量会破坏封装,建议尽量通过参数和返回值传递。
### 1.
*args和
**kwargs的正确使用姿势
笔记提到了“可变参数”,但实战中它们能极大提升灵活性。
-
*args接收任意个位置参数,打包成**元组**。
-
**kwargs接收任意个关键字参数,打包成**字典**。
```python
def demo(*args, **kwargs):
print('位置参数:', args)
print('关键字参数:', kwargs)
demo(1,2,3, name='lgl', age=18)
# 输出:
# 位置参数: (1,2,3)
# 关键字参数: {'name':'lgl','age':18}
```
**高阶用法**:将已有的列表/字典“解包”传递:
```python
params = {'name':'lgl', 'age':18}
def show(name, age):
print(f'{name} is {age}')
show(**params) # 等价于 show(name='lgl', age=18)
nums = [1,2,3]
def add(a,b,c):
return a+b+c
add(*nums) # 等价于 add(1,2,3)
```
**注意**:参数名必须匹配,否则
TypeError。
---
## 十三、综合实战:把笔记里的代码串起来
笔记末尾有一段示例代码:
```python
a = 10
print(a)
print(f'a={a}')
a = int(input('请输入一个整数:'))
print(a)
print(type(a))
import random
print(random.randint(1,100))
print(random.uniform(1,100))
```
我们可以把这些揉进一个**随机数猜谜游戏**,涵盖输入、类型转换、条件、循环、随机数和函数:
```python
import random
def guess_game():
target = random.randint(1, 100)
attempts = 0
while True:
try:
guess = int(input('猜一个 1~100 的整数:'))
except ValueError:
print('请输入有效整数!')
continue
attempts += 1
if guess < target:
print('太小了')
elif guess > target:
print('太大了')
else:
print(f'恭喜!用了 {attempts} 次猜中')
break
if __name__ == '__main__':
guess_game()
```
这个例子用到了
random.randint、
input、
int转型、
try-except、
if-elif-else、
while、
break、函数定义、
if __name__保护——几乎覆盖了笔记所有核心语法。
---
## 最后:你的基础,是否经得起“拷问”?
我们重新走了一遍笔记,但**重点始终放在那些“你以为你知道,实际可能错”的细节上**。下面整理一份**快速自查清单**,你可以逐条过一遍:
- 我是否清楚
"""是字符串而非真正的注释?
- 我是否会在
input后立即转型而不做异常处理?
- 我是否知道
random.uniform是闭区间(理论)?
- 我是否明白
and/
or返回的是操作数而非布尔值?
- 我是否习惯用
''.join()而不是
+拼接大量字符串?
- 我是否把
s.replace()的结果重新赋值了?
- 我是否知道
sort()返回
None且修改原列表,而
sorted()返回新列表?
- 我是否能在循环中安全删除字典元素?
- 我是否会用
*args和
**kwargs解包传参?
- 我是否清楚元组不可变但内部列表可变的特性?
如果每一项你都能自信点头,那么恭喜——你的基础真正“毕业”了。如果有一些模棱两可,不妨回头再翻翻对应章节。
**技术之路,不怕慢,就怕“我以为”。** 笔记是死的,但代码是活的。多写、多调试、多复盘,把每一个“知道”变成“做到”,才是进阶的唯一捷径。