你可使用 Lambda 表达式建立匿名函数,即没有名称的函数。lambda 表达式很是适合快速建立在代码中之后不会用到的函数。尤为对高阶函数或将其余函数做为参数的函数来讲,很是实用。python
咱们可使用 lambda 表达式将如下函数less
def multiply(x, y): return x * y
简写为:函数
double = lambda x, y: x * y
测试
lambda
表示这是一个 lambda 表达式。lambda
以后是该匿名函数的一个或多个参数(用英文逗号分隔),而后是一个英文冒号 :
。和函数类似,lambda 表达式中的参数名称是随意的。map()
是一个高阶内置函数,接受函数和可迭代对象做为输入,并返回一个将该函数应用到可迭代对象的每一个元素的迭代器。下面的代码使用 map()
计算 numbers
中每一个列表的均值,并建立列表 averages
。测试运行这段代码,看看结果如何。spa
经过将 mean
函数替换为在 map()
的调用中定义的 lambda 表达式,重写这段代码,使代码更简练。code
numbers = [ [34, 63, 88, 71, 29], [90, 78, 51, 27, 45], [63, 37, 85, 46, 22], [51, 22, 34, 11, 18] ] def mean(num_list): return sum(num_list) / len(num_list) averages = list(map(mean, numbers)) print(averages)
我这么改:orm
mean = lambda num_list: sum(num_list) / len(num_list) averages = list(map(mean, numbers))
但其实能够直接将lambda整个写到map参数中averages = list(map(lambda x: sum(x) / len(x), numbers))
对象
filter()
是一个高阶内置函数,接受函数和可迭代对象做为输入,并返回一个由可迭代对象中的特定元素(该函数针对该元素会返回 True)组成的迭代器。下面的代码使用 filter()
从 cities
中获取长度少于 10 个字符的名称以建立列表 short_cities
。测试运行这段代码,看看结果如何。ip
经过将 is_short
函数替换为在 filter()
的调用中定义的 lambda 表达式,重写这段代码,使代码更简练。内存
cities = ["New York City", "Los Angeles", "Chicago", "Mountain View", "Denver", "Boston"] def is_short(name): return len(name) < 10 short_cities = list(filter(is_short, cities)) print(short_cities)
改成 short_cities = list(filter(lambda x: len(x) < 10, cities))
迭代器是每次能够返回一个对象元素的对象,例如返回一个列表。咱们到目前为止使用的不少内置函数(例如 enumerate)都会返回一个迭代器。
迭代器是一种表示数据流的对象。这与列表不一样,列表是可迭代对象,但不是迭代器,由于它不是数据流。
生成器是使用函数建立迭代器的简单方式。也可使用类定义迭代器,更多详情请参阅此处。
下面是一个叫作 my_range
的生成器函数,它会生成一个从 0 到 (x - 1) 的数字流。
def my_range(x): i = 0 while i < x: yield i i += 1
注意,该函数使用了 yield
而不是关键字 return。这样使函数可以一次返回一个值,而且每次被调用时都从停下的位置继续。关键字 yield 是将生成器与普通函数区分开来的依据。
请本身写一个效果和内置函数 enumerate
同样的生成器函数。
以下所示地调用该函数:
lessons = ["Why Python Programming", "Data Types and Operators", "Control Flow", "Functions", "Scripting"] for i, lesson in my_enumerate(lessons, 1): print("Lesson {}: {}".format(i, lesson))
应该会输出:
Lesson 1: Why Python Programming Lesson 2: Data Types and Operators Lesson 3: Control Flow Lesson 4: Functions Lesson 5: Scripting
my_enumerate
函数实现:
def my_enumerate(iterable, start=0): """ return enumerate iterable """ for x in zip(range(start, len(iterable)+start), iterable): yield x
若是可迭代对象太大,没法完整地存储在内存中(例如处理大型文件时),每次可以使用一部分颇有用。
实现一个生成器函数 chunker
,接受一个可迭代对象并每次生成指定大小的部分数据。
以下所示地调用该函数:
for chunk in chunker(range(25), 4): print(list(chunk))
应该会输出:
[0, 1, 2, 3] [4, 5, 6, 7] [8, 9, 10, 11] [12, 13, 14, 15] [16, 17, 18, 19] [20, 21, 22, 23] [24]
chunker
函数实现以下:
def chunker(iterable, size): """Yield successive chunks from iterable of length size.""" for i in range(0, len(iterable), size): yield iterable[i:i + size]
可迭代的range()
很强大,能够用len()
也能够用切片。
你可能会疑问,为什么要使用生成器,而不使用列表。下面这段摘自 stack overflow 页面 的内容回答了这个问题:
生成器是构建迭代器的 “懒惰” 方式。当内存不够存储完整实现的列表时,或者计算每一个列表元素的代价很高,你但愿尽可能推迟计算时,就可使用生成器。可是这些元素只能遍历一次。
另外一种详细的解释以下(详细说明参见 该 stack overflow 页面。)
因为使用生成器是一次处理一个数据,在内存和存储的需求上会比使用list方式直接所有生成再存储节省不少资源。
由此区别,在处理大量数据时,常用生成器初步处理数据后,再进行长期存储,而不是使用 list。由于不管使用生成器仍是 list,都是使用过就要丢弃的临时数据。既然功能和结果同样,那就不如用生成器。
可是生成器也有本身的局限,它产生的数据不能回溯,不像list能够任意选择。