跳转至

Python 入门 / Python 基础补充

本文补充 Python 脚本中常见但稍容易混淆的语法。阅读前建议先掌握 Python 入门 / Python 基础

1. 函数参数

1.1 位置参数和关键字参数

调用函数时,可以按定义顺序传入位置参数,也可以明确写出参数名:

Python
1
2
3
4
5
6
7
def connect(host, port, timeout=3):
    print(host, port, timeout)


connect('example.com', 443)
connect(host='example.com', port=443, timeout=5)
connect('example.com', timeout=5, port=443)

输出:

Text Output
1
2
3
example.com 443 3
example.com 443 5
example.com 443 5

位置参数必须位于关键字参数之前。明确写出含义不直观的参数名,通常更容易阅读。

1.2 解包参数

调用函数时,* 将列表或元组解包为位置参数,** 将字典解包为关键字参数:

Python
1
2
3
4
5
6
7
def show_user(name, age, city):
    print(name, age, city)


position_args = ['Tom', 25]
keyword_args  = {'city': 'Shanghai'}
show_user(*position_args, **keyword_args)

输出:

Text Output
1
Tom 25 Shanghai

字典中的键必须与函数参数名对应,且同一个参数不能被重复传入。

1.3 接收不定数量的参数

定义函数时,*args 收集多余的位置参数并组成元组,**kwargs 收集多余的关键字参数并组成字典:

Python
1
2
3
4
5
6
7
def log_event(event, *tags, **details):
    print('event:', event)
    print('tags:', tags)
    print('details:', details)


log_event('login', 'security', 'user', user_id='u-001', success=True)

输出:

Text Output
1
2
3
event: login
tags: ('security', 'user')
details: {'user_id': 'u-001', 'success': True}

只有确实需要接受可变参数时才使用 *args**kwargs。参数含义固定时,明确列出参数名更利于检查和维护。

1.4 仅限关键字的参数

参数列表中单独的 * 表示其后的参数只能按名称传入:

Python
1
2
3
4
5
def request(url, *, timeout=3, use_cache=True):
    print(url, timeout, use_cache)


request('https://example.com', timeout=5, use_cache=False)

这种写法适合布尔值、超时时间等仅看位置难以理解的参数。

1.5 避免可变默认值

默认参数只在函数定义时创建一次。不要把列表、字典或集合直接作为默认值:

Python
1
2
3
4
5
6
7
8
9
def append_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items


print(append_item('a'))
print(append_item('b'))

输出:

Text Output
1
2
['a']
['b']

使用 None 并在函数内部创建新容器,可以避免不同调用意外共享同一个对象。

2. Lambda 表达式与推导式

2.1 Lambda 表达式

Lambda 表达式用于创建只包含一个表达式的匿名函数,语法结构如下:

Python
1
2
3
4
5
6
def add(x, y):
    return x + y


lambda_add = lambda x, y: x + y
print(add(1, 2) == lambda_add(1, 2))

输出:

Text Output
1
True

Lambda 表达式适合用作排序键等简短参数:

Python
1
2
3
4
5
6
7
users = [
    {'name': 'Tom', 'age': 25},
    {'name': 'Jerry', 'age': 18},
]

result = sorted(users, key=lambda user: user['age'])
print(result)

逻辑超过一个简单表达式时,使用具名函数通常更清晰。

2.2 列表推导式

列表推导式可以从一个可迭代对象生成新列表:

Python
1
2
3
4
5
6
numbers      = [1, 2, 3, 4, 5]
squares      = [number ** 2 for number in numbers]
even_squares = [number ** 2 for number in numbers if number % 2 == 0]

print(squares)
print(even_squares)

输出:

Text Output
1
2
[1, 4, 9, 16, 25]
[4, 16]

字典和集合也有类似的推导式:

Python
1
2
3
4
5
6
names          = ['Tom', 'Jerry', 'Tom']
name_lengths   = {name: len(name) for name in names}
unique_lengths = {len(name) for name in names}

print(name_lengths)
print(sorted(unique_lengths))

输出:

Text Output
1
2
{'Tom': 3, 'Jerry': 5}
[3, 5]

推导式包含嵌套循环或复杂条件时,应改用普通 for 循环以保持可读性。

3. 真假值

ifwhilebool() 会按真假值规则判断对象。以下常见值会被判断为假:

  • None
  • 数字零,例如 00.0
  • 空字符串 ""
  • 空容器,例如 [](){}set()
  • 布尔值 False

其他大多数对象会被判断为真:

Python
1
2
3
4
values = [0, 1, '', 'False', [], [0], None]

for value in values:
    print(f'{value!r}: {bool(value)}')

输出:

Text Output
1
2
3
4
5
6
7
0: False
1: True
'': False
'False': True
[]: False
[0]: True
None: False

字符串 "False" 不是布尔值 False;它是非空字符串,因此真假值为真。

检查容器是否为空时可以直接使用真假值:

Python
1
2
3
4
items = []

if not items:
    print('列表为空')

4. 常用内置函数

4.1 遍历与配对

Python
1
2
3
4
5
6
7
8
names  = ['Tom', 'Jerry', 'Lucy']
scores = [90, 80, 95]

for index, name in enumerate(names, start=1):
    print(index, name)

for name, score in zip(names, scores):
    print(f'{name}: {score}')

输出:

Text Output
1
2
3
4
5
6
1 Tom
2 Jerry
3 Lucy
Tom: 90
Jerry: 80
Lucy: 95

zip() 以最短的输入为准,较长输入中多余的元素不会出现在结果中。

4.2 聚合与判断

Python
1
2
3
4
5
6
7
8
9
numbers    = [3, 1, 4, 2]
conditions = [True, True, False]

print('元素数量:', len(numbers))
print('最小值:', min(numbers))
print('最大值:', max(numbers))
print('总和:', sum(numbers))
print('全部为真:', all(conditions))
print('至少一个为真:', any(conditions))

输出:

Text Output
1
2
3
4
5
6
元素数量: 4
最小值: 1
最大值: 4
总和: 10
全部为真: False
至少一个为真: True

4.3 排序

sorted() 返回排序后的新列表,可以通过 key 指定排序依据,通过 reverse=True 倒序排列:

Python
1
2
3
4
5
6
7
8
users = [
    {'name': 'Tom', 'age': 25},
    {'name': 'Jerry', 'age': 18},
    {'name': 'Lucy', 'age': 30},
]

result = sorted(users, key=lambda user: user['age'], reverse=True)
print([user['name'] for user in result])

输出:

Text Output
1
['Lucy', 'Tom', 'Jerry']

4.4 类型转换

Python
1
2
3
4
5
6
print(int('5'))
print(float('2.5'))
print(str(100))
print(list((1, 2, 3)))
print(tuple([1, 2, 3]))
print(set([1, 1, 2, 3]))

输出集合时顺序不固定;如果需要稳定结果,可以先使用 sorted()

range() 是惰性可迭代对象,zip()map()filter() 返回迭代器。它们可以直接用于 for,只有确实需要完整列表时才调用 list()

5. 字符串格式化

推荐使用 f-string 组合变量和文本:

Python
1
2
3
4
5
6
7
8
name  = 'Tom'
age   = 25
score = 92.456

print(f'{name} 今年 {age} 岁')
print(f'得分:{score:.2f}')
print(f'完成率:{0.856:.1%}')
print(f'调试表示:{name!r}')

输出:

Text Output
1
2
3
4
Tom 今年 25 岁
得分:92.46
完成率:85.6%
调试表示:'Tom'

常见格式说明如下:

写法 作用
{value:.2f} 浮点数保留两位小数
{value:.1%} 转换为百分比并保留一位小数
{value:>10} 在宽度为 10 的区域中右对齐
{value!r} 使用 repr() 的表示形式

6. 常用字符串方法

6.1 查找和判断

Python
1
2
3
4
5
6
7
text = 'Hello, Python!'

print(text.startswith('Hello'))
print(text.endswith('!'))
print('Python' in text)
print(text.find('Python'))
print(text.count('o'))

输出:

Text Output
1
2
3
4
5
True
True
True
7
2

str.find() 找不到内容时返回 -1str.index() 找不到内容时抛出 ValueError。只判断是否包含时,优先使用 in

6.2 分割和合并

Python
1
2
3
4
5
text  = 'apple,microsoft,ibm'
items = text.split(',')

print(items)
print(' | '.join(items))

输出:

Text Output
1
2
['apple', 'microsoft', 'ibm']
apple | microsoft | ibm

str.join() 只能合并字符串。如果列表中含数字,应先将每个元素转换为字符串。

6.3 清理和替换

Python
1
2
3
4
5
6
text = '  Hello, World!  '

print(repr(text.strip()))
print(repr(text.lstrip()))
print(repr(text.rstrip()))
print(text.strip().replace('World', 'Python'))

输出:

Text Output
1
2
3
4
'Hello, World!'
'Hello, World!  '
'  Hello, World!'
Hello, Python!

strip(chars) 中的参数表示需要移除的字符集合,不是完整前缀或后缀。需要移除固定前缀或后缀时,使用 removeprefix()removesuffix()

Python
1
2
print('prefix-value'.removeprefix('prefix-'))
print('report.json'.removesuffix('.json'))

7. 可变对象与复制

列表、字典和集合是可变对象。把可变对象赋给另一个变量不会自动复制数据,两个变量仍指向同一个对象:

Python
1
2
3
4
5
original = [1, 2]
alias    = original
alias.append(3)

print(original)

输出:

Text Output
1
[1, 2, 3]

需要独立的浅层副本时,可以使用 .copy()

Python
1
2
3
4
5
6
original = [1, 2]
copied   = original.copy()
copied.append(3)

print(original)
print(copied)

输出:

Text Output
1
2
[1, 2]
[1, 2, 3]

浅层复制不会继续复制内部嵌套对象。处理嵌套数据且确实需要完全独立的副本时,可以使用标准库 copy.deepcopy(),但应先确认复制大量数据带来的开销。

8. 下一步

接下来阅读 Python 入门 / Python 内置库,学习如何使用 Python 自带的标准库完成常见任务。