掌握这些高级Python技巧,让你的编程事半功倍_生成器前言

作者:Ravindra Parmar

Python是一种面向对象的语言,它与英语非常相似,因此对于初学者来说是一种非常好的语言。它的高级特性和受支持的库包甚至可以用几行代码来编写复杂的任务。在本文中,我们将介绍python的一些高级特性,掌握这些特性可以让你的编程更加顺畅。


01

列表解析

列表解析为无处不在的for循环提供了一种更简短、更好的替代方法。它用于我们需要对列表中的每个元素执行操作的迭代上下文中。


语法:

[some_operation(element) for element in sequence]
- returns list of elements.


举例:

# Python program to segregate positive and negative numbers in an array.
def segregate(arr):
return [x for x in arr if x%2 == 0] + [x for x in arr if x%2 != 0]


if __name__ == '__main__':
arr = [1, 8, 5, 3, 2, 6, 7, 10]
arr = segregate(arr)
print (arr)
# prints [8, 2, 6, 10, 1, 5, 3, 7]


们用列表解析的方法将一个列表分成两个列表重新拼接。第一个列表要挑选出所有的偶数,第二个列表挑选出所有的奇数。

02

切片

切片(slice)用于从给定的序列中提取元素的连续序列/子序列。默认情况下,step_size为1,因此生成一个连续序列。但是,我们可以为step_size提供任何值来获得非连续的元素序列。


举例:

# Python program to rotate an array by 'd' elements.
def rotate(arr, d):
return arr[d:] + arr[:d]


if __name__ == '__main__':
arr = [1, 2, 3, 4, 5, 6, 7, 8]
arr = rotate(arr, 3)
print (arr)
# prints [3 ,4, 5, 6, 7, 8, 1, 2]



这里,我们再次连接两个切片操作的结果(列表)。首先,我们将列表从索引' d '切片到结束,然后从开始切片到索引' d '。


# Python program to reverse an array.
def reverse(arr):
return arr[::-1]


if __name__ == '__main__':
arr = [1, 2, 3, 4, 5, 6, 7, 8]
arr = reverse(arr)
print (arr)
# prints [8 ,7, 6, 5, 4, 3, 2, 1]


这是一个显示step_size用法的例子。步长为-1表示从结束到开始切片。


03

Lambda

Lambda是一个匿名函数,它只包含一个表达式。它基本上是函数的简写,可以在任何需要表达式的地方使用。


举例:


import math
square_root = lambda x: math.sqrt(x)
# is an equivalant lambda expression for below function


def square_root(x):
return math.sqrt(x)


这里lambda函数用来表示对一个数求根号的函数。

04

Map

Map用于需要对元素序列应用函数/lambda的场景。尽管您几乎总是可以用列表解析来代替使用映射的需求。


举例:

# Square the numbers in the list.
import math


if __name__ == '__main__':
arr = [1, 2, 3, 4, 5]
arr = list(map(lambda x : x**2, arr))
print (arr)
# prints [1, 4, 9, 16, 25]

Map用于对序列中的每个元素进行平方。由于map返回一个iterable,我们需要用所需的类型(上面例子中的列表)包装结果。

05

Filter

另一方面,Filter对一个元素序列应用一个函数/lambda,并返回该函数/lambda返回True的元素序列。


# Print all even numbers in an array.
if __name__ == '__main__':
arr = [1, 2, 3, 4, 5, 6]
arr = list(filter(lambda x : x%2 == 0, arr))
print (arr)
# print [2, 4, 6]


这里,我们应用过滤器只返回序列中的偶数。

06

生成器

生成器是创建迭代器的简单方法。更正式地说,生成器是返回一个对象(迭代器)的函数,我们可以迭代该对象(一次一个值)。如果我们在python中从头开始编写相同的功能,它应该是这样的:


# Iterator for next power of two.
class NextPowTwo:
def __init__(self, max_ele = 0):
self.max_ele = max_ele

def __iter__(self):
self.n = 0
return self


def __next__(self):
if self.n <= self.max_ele:
result = 2 ** self.n
self.n += 1
return result
else:
raise StopIteration


if __name__ == '__main__':
it = iter(NextPowTwo(20))
print (next(it)) # prints '1'
print (next(it)) # prints '2'
print (next(it)) # prints '4'
print (next(it)) # prints '8'
view raw
power2iterator.py hosted with ❤ by GitHub



然而,实际的python不会让我们这么麻烦。下面是使用生成器的类似内容。正如您所看到的,上面提到的内容(调用__iter__()和__next__())都是由生成器自动处理的:


# Generator for next power of two.
def NextPowTwo(max_ele):
n = 0
while n < max_ele:
yield 2 * n
n += 1
raise StopIteration



obj = NextPowTwo(20)
print (obj.next())
print (obj.next())
print (obj.next())
print (obj.next())


生成器是通过使用yield语句而不是return语句i定义一个普通函数来创建的。如果函数包含至少一个yield语句,它就成为一个生成器函数。yield和return都将从函数返回一些值。函数在执行return时终止,而yield语句暂停函数,保存它的所有状态,然后在后续调用时继续执行。


一个生成器包含以下内容:




  • 至少有一个yield语句。
  • 返回一个对象(迭代器),但不立即开始执行。
  • 记住连续调用之间的局部变量及其状态。
  • 实现迭代协议