python散装笔记——141: 列表解构(也称为打包和解包)

liftword3个月前 (03-14)技术文章15

1: 解构赋值

在赋值中,可以使用“解包”语法将可迭代对象拆分为多个值:

解构为值

a, b = (1, 2)
print(a)
# Prints: 1
print(b)
# Prints: 2

如果尝试解包的元素数量多于可迭代对象的长度,将会引发错误:

a, b, c = [1]
# Raises: ValueError: not enough values to unpack (expected 3, got 1)

解构为列表

可以使用以下语法解包未知长度的列表:

head, *tail = [1, 2, 3, 4, 5]

这里,我们将第一个值提取为标量,其他值提取为列表:

print(head)
# Prints: 1
print(tail)
# Prints: [2, 3, 4, 5]

这相当于:

l = [1, 2, 3, 4, 5]
head = l[0]
tail = l[1:]

它也适用于多个元素或列表末尾的元素:

a, b, *other, z = [1, 2, 3, 4, 5]
print(a, b, z, other)
# Prints: 1 2 5 [3, 4]

在解构赋值中忽略值

如果只对给定的值感兴趣,可以使用_来表示你对其他值不感兴趣。注意:这仍然会设置_,只是大多数人不会将其用作变量。

a, _ = [1, 2]
print(a)
# Prints: 1
a, _, c = (1, 2, 3)
print(a)
# Prints: 1
print(c)
# Prints: 3

在解构赋值中忽略多个值

最后,可以使用_*语法在赋值中忽略多个值:

a, *_ = [1, 2, 3, 4, 5]
print(a)
# Prints: 1

这本身并不特别有趣,因为你可以直接使用列表索引来实现。真正有趣的是在一次赋值中保留第一个和最后一个值:

a, *_, b = [1, 2, 3, 4, 5]
print(a, b)
# Prints: 1 5

或者一次性提取多个值:

a, _, b, _, c, *_ = [1, 2, 3, 4, 5, 6]
print(a, b, c)
# Prints: 1 3 5

2: 打包函数参数

在函数中,可以定义一些强制性参数:

def fun1(arg1, arg2, arg3):
  return (arg1,arg2,arg3)

这将使函数仅在提供三个参数时可调用:

fun1(1, 2, 3)

你也可以通过使用默认值将参数定义为可选的:

def fun2(arg1='a', arg2='b', arg3='c'):
  return (arg1,arg2,arg3)

这样你可以以多种方式调用函数,例如:

fun2(1) # 返回:  (1,b,c)
fun2(1, 2) # 返回:  (1,2,c)
fun2(arg2=2, arg3=3) # 返回: (a,2,3)
...

但你也可以使用解构语法打包参数,以便使用列表或dict分配变量。

打包列表参数

假设你有一个值的列表:

l = [1,2,3]

你可以使用*语法将列表作为参数传递给函数:

fun1(*l)
# 返回: (1,2,3)
fun1(*['w', 't', 'f'])
# 返回: ('w','t','f')

但如果提供的列表长度与参数数量不匹配:

fun1(*['oops'])
# 抛出异常 TypeError: fun1() missing 2 required positional arguments: 'arg2' and 'arg3'

打包关键字参数

现在,你也可以使用字典打包参数。你可以使用**运算符告诉Python将dict解包为参数值:

d = {
  'arg1': 1,
  'arg2': 2,
  'arg3': 3
}
fun1(**d)
# 返回: (1, 2, 3)

当函数只有位置参数(没有默认值的参数)时,你需要字典包含所有预期的参数,且不能有多余的参数,否则会报错:

fun1(**{'arg1':1, 'arg2':2})
# 抛出异常: TypeError: fun1() missing 1 required positional argument: 'arg3'
fun1(**{'arg1':1, 'arg2':2, 'arg3':3, 'arg4':4})
# 抛出异常: TypeError: fun1() got an unexpected keyword argument 'arg4'

对于具有可选参数的函数,你可以以相同的方式将参数打包为字典:

fun2(**d)
# 返回: (1, 2, 3)

但你可以省略一些值,因为它们将被默认值替换:

fun2(**{'arg2': 2})
# 返回: ('a', 2, 'c')

和之前一样,你不能提供不存在的参数的额外值:

fun2(**{'arg1':1, 'arg2':2, 'arg3':3, 'arg4':4})
# 抛出异常: TypeError: fun2() got an unexpected keyword argument 'arg4'

在实际使用中,函数可以同时具有位置参数和可选参数,其工作方式相同:

def fun3(arg1, arg2='b', arg3='c'):
  return (arg1, arg2, arg3)

你可以只用一个可迭代对象调用函数:

fun3(*[1])
# 返回: (1, 'b', 'c')
fun3(*[1,2,3])
# 返回: (1, 2, 3)

或者只用一个字典:

fun3(**{'arg1':1})
# 返回: (1, 'b', 'c')

fun3(**{'arg1':1, 'arg2':2, 'arg3':3})
# 返回: (1, 2, 3)

或者在同一个调用中同时使用两者:

fun3(*[1,2], **{'arg3':3})
# 返回: (1,2,3)

但要注意,你不能为同一个参数提供多个值:

fun3(*[1,2], **{'arg2':42, 'arg3':3})
# 抛出异常: TypeError: fun3() got multiple values for argument 'arg2'

3: 解包函数参数

当您希望创建一个可以接受任意数量参数的函数,并且不在“编译”时强制参数的位置或名称时,这是可能的,方法如下:

def fun1(*args, **kwargs):
  print(args, kwargs)

*args**kwargs参数是特殊的参数,分别设置为一个tuple和一个dict

fun1(1,2,3)
# Prints: (1, 2, 3) {}
fun1(a=1, b=2, c=3)
# Prints: () {'a': 1, 'b': 2, 'c': 3}
fun1('x', 'y', 'z', a=1, b=2, c=3)
# Prints: ('x', 'y', 'z') {'a': 1, 'b': 2, 'c': 3}

如果你查看足够多的Python代码,你会很快发现它被广泛用于将参数传递给另一个函数。例如,如果你想扩展字符串类:

class MyString(str):
  def __init__(self, *args, **kwarg):
    print('Constructing MyString')
    super(MyString, self).__init__(*args, **kwarg)

相关文章

Python程序员必看!10分钟搞定项目打包:PyInstaller保姆级教程

一、为什么要打包Python程序?很多新手在学会Python编程后,都会遇到这样的尴尬:写了个实用工具却不会发给别人用代码文件必须要求对方安装Python环境源代码直接暴露存在安全风险PyInstal...

PyOxidizer:将 Python 应用打包成单一可执行文件的神器

三、PyOxidizer 基本使用使用 PyOxidizer 打包应用的基本流程如下:1. 创建新项目首先,我们使用 pyoxidizer init 命令创建一个新的 PyOxidizer 项目:py...

Python应用打包指南:如何将Python脚本打包成可执行文件

在Python开发中,我们经常会编写一些实用脚本或应用。但如何让这些脚本在没有安装Python环境的机器上也能运行呢?答案就是将Python脚本打包成可执行文件。今天,我们就来聊聊如何使用PyInst...

30s带你使用Python打包exe文件,并修改其图标

在 Python 中,我们可以使用PyInstaller或cx_Freeze等工具将 Python 脚本打包成可执行文件(.exe),并且能够修改生成的.exe文件的图标。使用 PyInstaller...

Pycharm将python文件打包为exe文件(详细:制作快捷功能)

很多朋友在使用pycharm编写程序后,想要把代码打包成带界面的EXE文件,方便后期的直接使用运行,现在面临着如何将python代码打包成exe的难题,这时候,带大家学习一下。首先,需要安装打包库方法...

一次打包,无限复用!教你用 PyCharm 搭建一劳永逸的开发环境

在开发过程中难免遇到开发半小时,环境整半天的尴尬。有时候自己辛苦在自己电脑上搭建的环境,却只能自己使用,无法复用给同事,这就造成了团队劳动力的极度浪费。在这里,明哥会给你介绍一种方法,可以让你辛辛苦苦...