Python进阶编程:编写更高效、优雅的Python代码
上QQ阅读APP看书,第一时间看更新

3.3.1 可迭代对象解压

可迭代对象的元素个数超过变量个数时,会抛出ValueError。要从可迭代对象中解压出N个元素,需要使用Python的星号表达式。

例如,在期末的时候,老师想统计家庭作业的平均成绩,但是需排除掉最高分和最低分。如果只有4门课程,可以直接用手动赋值操作,但如果有10门或更多课程,星号表达式就派上用场了,示例如下:


def drop_start_end(subjects):
    start, *middle, end = subjects 
    return avg(middle)

假设一些用户的记录列表中,每条记录包含名字、邮件地址,以及不确定数量的电话号码。若需要将这些记录按名字、邮件地址、电话号码的形式拆分,我们可采用以下代码:


def name_email_phone_split(record):
    name, email, *phone_numbers = record 
    return name, eamil, phone_numbers

注意 星号表达式解压出的变量永远是列表类型,所以对于星号表达式,就没有必要做多余的类型检查了。

星号表达式也能用在列表的开始部分。如我们有前8个月收入数据的序列,但是想对比一下最近一个月的收入和前面7个月的平均值,可以采用类似如下的编码:


def income_exp(income_record):
    *income_pre_month, current_month = income_record
    income_avg = sum(income_pre_month) / len(income_pre_month)
    return avg_comparison(income_avg, current_month)

扩展的迭代解压语法是专门为解压不确定个数或任意个数元素的可迭代对象而设计的。通常,这些可迭代对象的元素结构有确定的规则(比如,第1个元素后面都是电话号码)。

星号表达式让开发人员可以很容易地解压元素,而不需通过一些比较复杂的手段去获取这些关联的元素值。

星号表达式在处理迭代元素为可变长元组的序列时是很有用的。

下面是一个带有标签的元组序列示例:


record_list = [
    ('f_func', 1, 2),
    ('d_func', 'hello world'),
    ('f_func', 'a', 'b'),
]
def f_func(x, y):
    print(f'f func:{x} {y}')


def d_func(s):
    print(f'd func:{s}')


for tag, *args in record_list:
    if tag == 'f_func':
        f_func(*args)
    elif tag == 'd_func':
        d_func(*args)

星号解压语法在字符串操作的时候也很有用,如对字符串的分割,示例如下:


str_v = 'hello:中国:three:123:World:/usr/exp:/home/my/path'
greet, *fields, home_path = str_v.split(':')
print(greet, home_path)

注意 对于解压后的元素,若想要丢弃,不建议直接使用*,可以使用下划线(_)或ign(ignore的缩写)表示要丢弃的元素。

在实际应用时,星号解压语法和列表处理有许多相似点,如使用星号解压语法可以很容易地将列表分割成前后两部分,示例如下:


num_list = [1, 3, 5, 7, 9]
head, *rest = num_list
print(f'head is:{head}, rest list is:{rest}')

这里展示了部分星号解压语法的使用,更多的使用方式读者可以自行尝试。

扩展:通过适当添加空行,可以使代码布局更为优雅、合理。

布局清晰、整洁、优雅的代码能够给读者带来愉悦感,也能帮助开发者进行良好的沟通。特别在团队开发中,良好的代码风格可以很好地帮助团队提高开发效率。

对于没有养成较好编码规范的开发者,建议先花点时间了解Python编码规范。