Skip to content

Latest commit

 

History

History
202 lines (121 loc) · 10.2 KB

5-advanced-tips-python-sequences.md

File metadata and controls

202 lines (121 loc) · 10.2 KB

Python 序列的 5 个高级技巧

原文:www.kdnuggets.com/2021/11/5-advanced-tips-python-sequences.html

评论

作者 Michael Berk,Tubi 的数据科学家

图片来源:NASAUnsplash


我们的前三大课程推荐

1. 谷歌网络安全证书 - 快速进入网络安全职业生涯。

2. 谷歌数据分析专业证书 - 提升你的数据分析技能

3. 谷歌 IT 支持专业证书 - 支持你所在组织的 IT


“66%的数据科学家每天都在使用 Python。” — src

如果你是那 66%中的一员,这篇文章就是为你准备的。

我们将涵盖Luciano Ramalho 的《流畅的 Python》第二章中的主要内容,该章节涉及序列,例如列表、元组等。

1 — 列表与元组

提示:列表应保存相同类型的信息,而元组可以保存不同类型的信息。

从基础开始,让我们讨论一下列表和元组之间的主要区别。下面我们可以看到每种的示例——列表用方括号[]括起来,而元组用圆括号() 括起来。

my_tuple = (1,'a',False)
my_list =  [1,'a',False]

在后端,列表是可变的,而元组则不是。不可变变量通常需要更少的内存,因此尽可能使用元组。

然而,《流畅的 Python》中涵盖了更深层次的内容。

从语义上讲,最好将不同的kinds的数据存储在元组中,将相同的kinds的数据存储在列表中。请注意,元组和列表都支持在同一变量中使用多种 Python 数据类型,但我们讨论的是变量的概念类型。

例如,一个元组可以用来存储以下信息:(latitude, longitude, city_name)。这些不仅是不同的数据类型(float, float, str),而且在概念上也不同。另一方面,列表仅应存储纬度、经度、城市名称或三者的元组。

# list of [float, float, str]
bad_practice_list = [[39.9526, 75.1652, 'Philadelphia'], 
                     [6.2476, 75.5658m 'Medellín']]# list of tuples
good_practice_list = [(39.9526, 75.1652, 'Philadelphia'), 
                      (6.2476, 75.5658m 'Medellín')]

为了提高 Python 代码的组织性,你应该始终将相同类型的信息保存在列表中。元组用于结构,列表用于序列。

2 — 解包可迭代对象

提示:使用*******_**来改进你的解包。

解包是一种非常流畅且易读的方式来访问可迭代对象中的值。它们在循环、列表推导式和函数调用中非常常见。

解包是通过将类序列的数据类型分配给以逗号分隔的变量名来完成的,例如……

x, y, z = (1,2,3)

然而,《流利的 Python》介绍了一些高级解包方法。例如,你可以使用*来解包可迭代对象中的“其余”项。使用星号符号是当你有一些感兴趣的项和其他不那么重要的项时很常见的做法。

x, *y, z = [1,2,3,4,5,6,7]
x #1
y #[2,3,4,5,6]
z #7

如你所见,*操作符可以出现在一组变量的中间,Python 会将所有未处理的值分配给该变量。

不过,我们可以进一步使用星号解包操作符。你可以使用_来解包并不保存一个值。这种惯例在你希望解包某些内容时很有用,但与上面的例子不同,你不需要所有的变量。

x, _ = (1,2)
x #1

下划线_解包操作符的一个使用场景是当你处理字典或内建方法返回多个值时。

最后,为了锦上添花,我们可以将这两种方法结合起来,解包而不保存“其余”值

x, *_ = (1,2,3,5,6)
x #1

3 — 函数是否返回 None?

提示:如果一个函数返回**None**,它执行的是原地操作。

许多 Python 数据类型有两个版本的相同函数,如下所示的x.sort()sorted(x)

x = [3,1,5,2]
x.sort()
x # [1,2,3,5]x = [3,1,5,2]
y = sorted(x)
x # [3,1,5,2]
y # [1,2,3,5]

在使用x.sort()的第一个例子中,我们执行的是原地排序,这更高效且占用更少的内存。但在使用sorted(x)的第二个例子中,我们能够保留列表的原始顺序。

通常,Python 保持这种符号约定。点操作符x.sort()通常返回None并进行原地变更。像sorted(x)这样的函数将变量作为参数,并返回变更后的变量的副本,但保持原始变量不变。

4 — 生成器表达式 vs. 列表推导式

提示:如果你只访问一次变量,请使用生成器表达式。如果不是,请使用列表推导式。

列表推导式(listcomps)和生成器表达式(genexps)是实例化序列数据类型的不同方法。

list_comp = [x for x in range(5)]
gen_exp = (x for x in range(5))

如上所示,列表推导式和生成器表达式之间唯一的语法区别是括号的类型——生成器表达式使用圆括号(),而列表推导式使用方括号[]

**列表推导式是实例化的,这意味着它们会被评估并保存在内存中。生成器表达式则不是。**每次程序需要生成器表达式时,它都会执行计算来评估该表达式。

所以这就是为什么生成器表达式在你只使用变量一次时更好的原因——它们实际上不会存储在内存中,因此效率更高。但是,如果你反复访问一个序列或需要列表特定的方法,最好将其存储在内存中。

有趣的附注——你还可以使用列表推导语法创建字典……

my_dict = {k:v for k,v in zip(['a','b'], [1,2])}

5 — 切片

最后,让我们简单总结一下切片。与解包不同,有时我们希望通过索引访问可迭代对象中的值。切片允许我们通过以下格式来做到这一点:my_list[start:stop:step]

对于那些知道my_list[::-1]可以反转列表顺序但不知道为什么(例如我自己),这就是原因。通过将-1作为步长参数传递,我们可以反向遍历列表。

现在大多数 Python 包遵循[start:stop:index]语法。Numpy 和 pandas 是一些显著的例子。让我们逐一看看每个参数……

  • start:你切片中的起始索引

  • end:你切片中的不包括的结束索引

  • step:你在startstop索引之间的步长(及方向)

因此,由于这些值都是可选的,我们可以进行各种有趣的切片操作……

x = [1,2,3,4]x[1:3]                   # [2,3]
x[2:0:-1]                # [3,2]last = [-1::]            # 4
all_but_last = x[:-1:]   # [1,2,3]
reversed = x[::-1]       # [4,3,2,1]

就这样!来自《流畅的 Python》第二章的 5 个主要技巧。还有一个部分……

数据科学家的有用笔记

声明,我并不特别有资格对这篇文章提出个人意见。不过,这些笔记应该相当直观。如果你不同意,请告诉我。

  1. 列表推导几乎总是应该替代循环。 如果循环体很复杂,你可以创建一个执行这些操作的函数。通过将用户定义的函数与列表推导语法结合起来,你可以编写出既可读又高效的代码。如果你需要迭代多个变量,可以使用[enumerate()](https://realpython.com/python-enumerate/)[zip()](https://www.w3schools.com/python/ref_func_zip.asp)

  2. 在 Python 中“优化”并不重要。 如果你在编写生产级代码,情况可能会有所不同。但实际上,使用元组与列表相比,你不会看到显著的性能提升。确保你的数据处理步骤逻辑清晰且高效是工作中的 99%。如果 1%很重要,那么你可以开始担心元组与列表的问题。此外,如果你真的关注高效代码,你可能不会使用 Python。

  3. 最后,切片非常酷。 我一直知道x[::-1]可以反转列表,但直到阅读《流畅的 Python》这一章节才明白原因。它同样适用于 numpy 和 pandas!

感谢阅读!我将再写 35 篇文章,将学术研究带入数据科学行业。查看我的评论以获取此文章的主要来源和一些有用资源的链接。

个人简介:Michael Berk (michaeldberk.com/) 是 Tubi 的数据科学家。

原文。已获授权转载。

相关:

  • 如何发现你的机器学习模型中的弱点

  • 使用这个 Python 库进行简单的文本抓取、解析和处理

  • 使用 Faker 在 Python 中生成简单的合成数据

更多相关主题