原文链接(侵删): http://treyhunner.com/2018/03/tuple-unpacking-improves-python-code-readability/

无论我是教python新手还是老手,经常发现他们没有很好的使用多重赋值。

多重赋值允许你在一行代码中同时分配多个值。也许你在了解它之后会觉得也不过如此嘛,但你要记住,多重赋值有可能会很棘手。

这篇文章就来详细的介绍下多重赋值。

多重赋值如何工作

在本文中,当我说到多重赋值,元组解包,迭代解包的时候,指的都是同一件事情。

python中的多重赋值看起来像这样:

x, y = 10, 20
复制代码

这里我们把x设为10,y设为20。

上面的代码实际上是创建了一个包含10,20的元组,然后循环遍历该元组,并从循环中获取两个items中的每一个,然后分别分配给x和y。

像这样:

(x, y) = (10, 20)
复制代码

在元组中使用括号是可选的,多重赋值也一样,下面这几行代码都是等价的:

x, y = 10, 20
x, y = (10, 20)
(x, y) = 10, 20
(x, y) = (10, 20)
复制代码

多元赋值通常被称为“元组拆包”,是因为它经常与元组一起使用。但是我们也可以对任何迭代使用多个赋值,而不仅仅是元组。比如使用列表:

>>> x, y = [10, 20]
>>> x
10
>>> y
20
复制代码

使用string:

>>> x, y = 'hi'
>>> x
'h'
>>> y
'i'
复制代码

任何可以循环的东西都可以通过元组解包/多重赋值来“解压缩”。

接下来说说如何使用多重赋值。

在循环中解压缩

你经常会在for循环中看到解压缩。

这里有一个dict:

>>> person_dictionary = {'name': "Trey", 'company': "Truthful Technology LLC"}
复制代码

通常我们不会对dict这样使用for循环:

for item in person_dictionary.items():print(f"Key {item[0]} has value {item[1]}")
复制代码

而是像下面这样,使用多重赋值:

for key, value in person_dictionary.items():print(f"Key {key} has value {value}")
复制代码

实际上,等同于把item赋值给key,value一样:

for item in person_dictionary.items():key, value = itemprint(f"Key {key} has value {value}")
复制代码

所以多重赋值非常适合把一个字典拆分成键值对的形式,这一用法在其他地方也很常见。

比如使用enumerate的时候:

for i, line in enumerate(my_file):print(f"Line {i}: {line}")
复制代码

同样的,在使用zip的时候:

for color, ratio in zip(colors, ratios):print(f"It's {ratio*100}% {color}.")
复制代码

多任务虽然适用于任何分配,但不仅仅是循环分配。

代替硬编码索引

我们经常会在代码中看到硬编码索引(像point[0], items[1]这样):

print(f"The first item is {items[0]} and the last item is {items[-1]}")
复制代码

我们可以用多重赋值来代替硬编码索引,这样能让代码的可读性更高。

比如,下面是一段有三个硬编码索引的代码:

def reformat_date(mdy_date_string):"""Reformat MM/DD/YYYY string into YYYY-MM-DD string."""date = mdy_date_string.split('/')return f"{date[2]}-{date[0]}-{date[1]}"
复制代码

通过使用多重赋值让这段代码可读性更高一些:

def reformat_date(mdy_date_string):"""Reformat MM/DD/YYYY string into YYYY-MM-DD string."""month, day, year = mdy_date_string.split('/')return f"{year}-{month}-{day}"
复制代码

所以当你在代码中见到硬编码索引时,停下来想想是否可以用多重赋值使得代码更可读。

多重赋值是很严格的

在解包我们给它的迭代时,多重赋值实际上相当严格。

如果试图将更大的迭代器拆分成更少的变量,会得到一个错误:

>>> x, y = (10, 20, 30)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
复制代码

同样的,如果试图将一个较小的迭代器拆分成更多的变量,也会得到一个错误:

>>> x, y, z = (10, 20)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
复制代码

这种严格的规定相当好,如果当前正在处理的item与我们预期的不同,可以及时的发现并修改。

切片的代替品

多重赋值也可以用来代替切片中的硬编码。

我们都知道,切片可以方便的获取列表或者其它序列中的部分元素。

像下面的代码就是硬编码的方式;

all_after_first = items[1:]
all_but_last_two = items[:-2]
items_with_ends_removed = items[1:-1]
复制代码

任何时候当你看到切片索引中使用硬编码的方式,你都可以使用多重赋值来代替。要做到这一点,我们需要用到* 操作符。

在python3中,* 操作符被加入到多重赋值的语法中,它允许我们在解包列表时使用* 代替剩余的部分,比如:

>>> numbers = [1, 2, 3, 4, 5, 6]
>>> first, *rest = numbers
>>> rest
[2, 3, 4, 5, 6]
>>> first
1
复制代码

* 操作符允许我们替换列表中的硬编码,下面的两行代码是等价的:

>>> beginning, last = numbers[:-1], numbers[-1]
>>> *beginning, last = numbers
复制代码

同样的:

>>> head, middle, tail = numbers[0], numbers[1:-1], numbers[-1]
>>> head, *middle, tail = numbers
复制代码

深入拆包

深入拆包是python程序员经常忽视的一个特性,虽然使用的不是很频繁,但是了解了之后将很有用。

对于下面的代码来说,并不算是深入拆包:

>>> color, point = ("red", (1, 2, 3))
>>> color
'red'
>>> point
(1, 2, 3)
复制代码

而下面的代码就可以这样说了,因为它将point元组进一步分为x,y,z三个变量:

>>> color, (x, y, z) = ("red", (1, 2, 3))
>>> color
'red'
>>> x
1
>>> y
2
复制代码

如果对上面的代码你感到困惑,它其实跟下面的代码是一样的,在两边加上括号即可:

>>> (color, (x, y, z)) = ("red", (1, 2, 3))
复制代码

首先通过第一层拆包得到两个对象,然后再将第二个对象拆包分配给x, y, z三个变量。

考虑下面两个列表:

start_points = [(1, 2), (3, 4), (5, 6)]
end_points = [(-1, -2), (-3, 4), (-6, -5)]
复制代码

下面的代码使用浅层拆包对列表进行操作:

for start, end in zip(start_points, end_points):if start[0] == -end[0] and start[1] == -end[1]:print(f"Point {start[0]},{start[1]} was negated.")
复制代码

我们用深层拆包可以做同样的事:

for (x1, y1), (x2, y2) in zip(start_points, end_points):if x1 == -x2 and y1 == -y2:print(f"Point {x1},{y1} was negated.")
复制代码

使用深层拆包能够更清晰的看到正在处理的对象,另外,深层拆包的过程同样严格。

多重赋值可以提高代码的可读性和代码的正确性。它可以使您的代码更具描述性,同时还可以对您要解包的迭代对象的大小和形状进行隐式断言。

多重赋值一个最常见的用途是替换硬编码索引和硬编码的列表。

转载于:https://juejin.im/post/5aace6746fb9a028b61749dc

(译)用多重赋值和元组解包提高python代码的可读性相关推荐

  1. Python3 元组解包情况总结

    前言: tuple作为不可变对象,每个tuple对象在第一次创建后,持有的元素不能改变,这是元组的基本概念.但元组解包功能是其中一个很常见的功能点,今天总结下元组解包的几种情况 情况一: 元组赋值给多 ...

  2. Python 进阶 - 元组解包

    1. 定义 什么是元组解包?元组解包也叫'元组拆包','迭代对象解包' 等.也就是把批量的数据进行批量的赋值.当然不只是tuple,任何可迭代对象都支持解包,还包括dict.set.string等一切 ...

  3. python行列式值计算程序_解行列式程序 python代码实现

    解行列式程序 python代码实现 制作背景 大二上学期结束要放假时,线性代数有一个小作业:做一个阶行列式的程序.由于我此时最熟悉的语言是Python,所以就用python做的.我猜到网上应该有很多答 ...

  4. unity游戏解包和修改代码

    主要软件 1.AssetStudio 用于解包资源 2.DNSPY 用于反编译代码并进行修改 3.ILSPY 同上,差不多功能 资源部份 下面拿steam游戏<传说法师>作为例子进行解包. ...

  5. 详解200行Python代码实现控制台版2048【总有一款坑适合你】【超详细】

    跟着实验楼学习了2048的Python实现,先丢个地址 200行Python代码实现2048 我接触Python时间不长,只了解一些基本的语法和容器,在学习的过程中遇到不少问题,这里做一个记录. cu ...

  6. plot参数详解python_30行Python代码实现3D数据可视化

    作者:潮汐 来源:Python技术 欢迎来到编程教室~ 我们之前的文章中有讲解过不少 Matplotlib 的用法,比如: 完成这50个Matplotlib代码,你也能画出优秀的图表 25个常用Mat ...

  7. 数字水印技术:LSB加密详解(附python代码)

    概要 数字水印是一种将标识信息嵌入到载体当中,且不影响载体使用的一种技术,主要分为时域水印嵌入算法(将水印嵌入到时域采样数据中)和变换域水印嵌入算法(先对音频做变换,将水印嵌入到变换域系数中).本文主 ...

  8. 获取数据 - 下载附件解压附件 - Python代码

    一些线上化刚刚起步的部门,并不是所有的数据都是直接推送到服务器的数据库中,有些数据往往是数据中心通过邮件形式推送的,如果每天接收邮件--下载附件--解压--合并文件--导入数据库,对于数据工程师来说, ...

  9. 用包管理python代码,提高开发效率

    有一个月没更新博客文章了,主要原因是我在摸索新知识,探索未知,以后有机会写写这段时间的成果,将会在linux编程专题继续更新. 现在我打算写一个新的专题Python编程来总结过去点点滴滴的收获.这个专 ...

最新文章

  1. android上方导航条跳转页面,《成为大前端》系列 7. 多页面、页面跳转和Navigation模块...
  2. 使用GPRS模块进行TCP/UDP连接的过程分析
  3. Linux提权:常用三种方法
  4. JAVA ReentrantLock 分析
  5. docker php composer 使用_如何使用Docker部署PHP开发环境
  6. md5与des算法有何不同_到底AI芯片和传统芯片有何区别?
  7. RabbitMQ 最新版安装 (Linux环境)
  8. VForum07之四:布道中国 解读本地化策略
  9. wordpress支持MySQL5.5_CentOS 5.5安装Nginx、PHP(FastCGI)、MySQL --搭建LNMP环境安装Wordpress...
  10. WEB的发展历程、Tomcat服务器、与HTTP协议
  11. java中普通变量、静态变量、静态代码块初始化的顺序辨析
  12. Xcode9 Could not receive a message from the device
  13. EasyUI仓库管理系统
  14. 【PS4开发】如何通过unity3d发布ps4应用
  15. Android获取本地IP
  16. 神经机器翻译(Neural machine translation, NMT)学习笔记
  17. 纽约峭石之巅观景台:从直入云天的城市之巅眺望纽约全景
  18. RelativeLayout.LayoutParams.addRule()方法
  19. [看门狗]基于Linux的嵌入式系统全程喂狗策略
  20. Visio中图形关于轴线对称

热门文章

  1. 白话Elasticsearch60-数据建模实战_Join datatype 父子关系数据建模
  2. Quartz-DateBuilder解读
  3. aboboo 上一句 快捷键_Word快捷键大全
  4. 超简单-用协程简化你的网络请求吧,兼容你的老项目和旧的网络请求方式
  5. 鸿蒙系统今日发布 中国人自己的操作系统,鸿蒙系统今日发布,中国人自己的操作系统...
  6. MATLAB使用Python数值和字符变量
  7. 火电厂给水控制系统设计
  8. java回退一格_api短信接口
  9. linux下mqm用户下S开头日志,Linux新建用户,切换后只显示$问题
  10. python django restful_详解Django rest_framework实现RESTful API