Python 技巧 - Iterable - 第一部分
介绍
编者注:本指南是实用 Python 技巧系列的一部分。阅读有关本系列的更多信息并在此处找到其他指南的链接。
在本指南中,我们将开始学习 Python 中的可迭代技巧,包括与可迭代相关的高级技能。每个 Python 技巧都分两个步骤进行解释:
- 概念的简要描述和交互式代码示例
- 一些鼓舞人心的例子来启发你
构造迭代器
以下是从Hackaday中摘取的迭代器的一些精细定义:
迭代器是一个表示数据流的对象。从技术上讲,它是一个具有__iter__和__next__方法的对象。
可迭代对象是能够迭代的对象。实际上,可迭代对象是具有__iter__方法的对象,该方法返回一个迭代器。字符串、列表、文件和字典都是可迭代对象的示例。
鼓舞人心的例子
这个例子对于迭代器来说是一个非常有创意的用法。in函数循环遍历同一个迭代器,以确保每个字符只按顺序检查一次。
"""construct iterator to make sure check every char only once by 'in' """
# L392: check if s is subsequence of t. s = "abc", t = "ahbgdc", return true.
def is_subsequence(s: str, t: str) -> bool:
t = iter(t)
return all(c in t for c in s)
构造生成器
生成器提供了一种简单的内置方法来创建迭代器实例。我们可以通过调用具有一个或多个yield表达式的函数来构建生成器。我们还可以用生成器表达式以理解的方式构造生成器,我们将在下面讨论。
生成器不会将所有值存储在内存中;它们会动态生成值。这是我们在Python 技巧 - 基础指南中讨论的惰性求值技术。
鼓舞人心的例子
为了简化逻辑,我们可以将结果构建为生成器样式。
"""generate all combinations of coins which sum to target amount"""
def get_coin_changes(coins: List[int], amount[int]) -> List[List[int]]:
for i, coin in enumerate(coins):
if coin == amount:
yield (coin,)
elif coin < amount:
yield from ((coin,) + x for x in change(coins[i:], amount - coin))
"""generate all combinations of well-formed n pairs of parentheses"""
# L22: generate all combinations of well-formed n pairs of parentheses.
def generate_parenthesis(n: int) -> List[str]:
def generate(p, left, right):
if 0 <= left <= right:
if not right:
yield p
for q in generate(p + '(', left-1, right): yield q
for q in generate(p + ')', left, right-1): yield q
return list(generate('', n, n))
理解
理解技术提供了一种基于现有序列构建新序列(如列表、集合、字典等)的简短而简洁的方法。
Python 提供以下四种类型的理解:
"""list comprehension"""
odds_list = [x for x in range(20) if x % 2]
"""generator_expression"""
odds_generator = (x for x in range(20) if x % 2)
"""set comprehension"""
odds_set = {x for x in range(20) if x % 2}
"""dict comprehension"""
square_dict = {x: x**2 for x in range(10)}
鼓舞人心的例子
以下示例演示了构建列表推导的高级技巧。它们还展示了各种应用场景。
"""bfs in list comprehension way"""
# L515: find the largest value in each row of a binary tree
def find_largest_in_binary_tree_rows(root: TreeNode) -> List[int]:
maxes, row = [], [root]
while any(row):
maxes.append(max(node.val for node in row))
row = [kid for node in row for kid in (node.left, node.right) if kid]
return maxes
"""rotate image by list comprehension"""
# L48: rotate the image by 90 degrees (clockwise)
def rotate_image_90_degrees(matrix: List[List[int]]) -> None:
matrix[:] = [[row[i] for row in matrix[::-1]] for i in range(len(A))]
"""generate combinations by list comprehension recursively"""
# L77: Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
def combine(n: int, k: int) -> List[List[int]]:
if k == 0:
return [[]]
# add last element
return [pre + [i] for i in range(k, n + 1) for pre in combine(i - 1, k - 1)]
"""generate binary trees by list comprehension recursively"""
# given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n.
def generate_binary_search_trees(last: int, first: int=1) -> List[TreeNode]:
def node(val, left, right):
node = TreeNode(val)
node.left = left
node.right = right
return node
return [node(root, left, right)
for root in range(first, last+1)
for left in generate_binary_search_trees(root-1, first)
for right in generate_binary_search_trees(last, root+1)] or [None]
拉姆达
lambda函数,也称为匿名函数,是具有隐式返回的单一表达式。lambda函数可以有任意数量的参数,但只能有一个表达式。
lambda arguments : expression
鼓舞人心的例子
下面的示例展示了lambda的各种应用场景。
"""lambda used in lexical closure"""
def make_adder(n):
return lambda x: x + n
plus_3 = make_adder(3)
plus_3(4)
# output: 7
"""lambda used in key"""
# sort dict by value
d = {'apple': 18, 'orange': 20, 'banana': 5, 'rotten tomato': 1}
sorted(d.items(), key=lambda x: x[1])
# alternative
from operator import itemgetter
sorted(d.items(), key=itemgetter(1))
# output: [('rotten tomato', 1), ('banana', 5), ('apple', 18), ('orange', 20)]
for pos in range(len(S)):
"""lambda used in filter"""
matched_words = list(filter(lambda x: S[pos:].startswith(x), words))
if matched_words:
"""lambda used in max"""
add_interval([pos, pos + len(max(matched_words, key=lambda x: len(x)))])
"""call lambda in nested"""
# L422: given a sequence of words, check whether it forms a valid word square.
def valid_word_square(words: List[str]) -> bool:
f = lambda x: map(None, *x) # python 2
return f(f(words)) == f(words)
"""use lambda to wrap parameter as callable"""
def wrapped_callable(f):
if callable(f): return f
else: return lambda: f
结论
在本指南中,我们学习了许多可迭代的 Python 技巧,例如迭代器、生成器、理解和 lambda。我希望其中一些对你有用。
在第 2 部分中,我们将继续学习其他可迭代的 Python 技巧。
您还可以从 Github下载示例笔记本iterables.ipynb 。
本指南是 Python 技巧指南系列之一:
- Python 技巧 - 简介
- Python 技巧 - 基础 - 第一部分
- Python 技巧 - 基础 - 第二部分
- Python 技巧 - Iterable - 第一部分
- Python 技巧 - Iterable - 第二部分
- Python 技巧 - 黑魔法 - 第一部分
- Python 技巧 - 黑魔法 - 第 2 部分
希望你喜欢。如果您有任何问题,欢迎通过 recnac@foxmail.com 与我联系。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~