sorted 、 reversed:用于序列排序和反转数据序列可能是任何编程语言中最常用的算法操作,Python 中的内置函数 sorted 和 reversed 都用于实现这些功能。
sorted 函数对输入的数据进行排序,并返回一个排序过的 list 对象。
>>> items = (3, 4, 1, 2)
>>> sorted(items)
[1, 2, 3, 4]
它使用 Tim Peters 发明的的“TimSort”算法,Tim Peters 是最早的 Python 大师之一。
sorted 还有另外两个参数:reverse 和 key 。当 reverse=True 时,对数据进行倒序排序;key 参数接受一个函数,该函数用于每个元素,根据每个项目的自定义属性对数据进行排序。来看看下面的代码:
>>> items = [
... {'value': 3},
... {'value': 1},
... {'value': 2},
... ]
>>> sorted(items, key=lambda d: d['value'])
[{'value': 1}, {'value': 2}, {'value': 3}]
>>> names = ['James', 'Kyle', 'Max']
>>> sorted(names, key=len) # Sorts by name length
['Max', 'Kyle', 'James']
还要注意,虽然 list.sort() 已经是对列表排序的一种方法,但 .sort() 方法只存在于列表中,而 sorted 可以接受任何可迭代对象。
reversed 函数接受任何序列类型,并返回一个生成器,它将原来对象中的成员顺序反序。
返回生成器是很好的,因为这意味着反转某些对象根本不需要额外的内存空间,比如 range 或 list ,它们的反转值可以逐个生成。
>>> items = [1, 2, 3]
>>> x = reversed(items)
>>> x
<list_reverseiterator object at 0x7f1c3ebe07f0>
>>> next(x)
3
>>> next(x)
2
>>> next(x)
1
>>> next(x)
StopIteration # Error: end of generator
>>> for i in reversed(items):
... print(i)
...
321
>>> list(reversed(items))
[3, 2, 1]
map 和 filter在 Python 中,所有东西都可能是对象,但这并不一定意味着 Python 代码需要面向对象。实际上,可以用 Python 编写非常易读的函数代码。
如果不知道什么是函数式语言或函数式代码,那么这里的概念是:所有的功能都是通过函数提供的。没有一个正式的类、对象、继承等概念。本质上,所有程序都只是操作数据片段,其方法是:将它们传递给函数并将修改后的值返回给你。
函数式编程中两个非常常见的概念是map和filter, Python为它们提供了内置函数:
map 是一个“高阶函数”,它是将另一个函数作为参数的一个函数。 例如:
>>> def square(x):
... return x * x
...
>>> numbers = [8, 4, 6, 5]
>>> list(map(square, numbers))
[64, 16, 36, 25]
>>> for squared in map(square, numbers):
... print(squared)
...
64
16
36
25
map 有两个参数:函数和序列,它通过将每个元素作为输入来运行该函数,并将所有输出存储在一个新列表中。 map(square, numbers) 获取每个数字并返回一个平方数列表。
注意,我必须使用 list(map(square, numbers)),这是因为 map 本身返回一个生成器。请求这些值时,它们会被惰性地一次映射一个,例如,如果循环一个 map 对象,它会在序列的每一项上逐个运行映射函数。这意味着 map 不会存储映射值的完整列表,也不会在不需要的时候浪费时间计算额外的值。
filter 非常类似于 map ,只不过,它不是将每个值映射到一个新值,而是根据条件过滤一系列的值。
这意味着 filter 的输出将包含与输入相同的项,除了一些项可能被丢弃。例如下面的例子,过滤掉奇数。
>>> items = [13, 10, 25, 8]
>>> evens = list(filter(lambda num: num % 2 == 0, items))
>>> evens
[10, 8]
一些人可能已经意识到这些函数本质上是在做与列表解析相同的事情,对的!
列表解析式基本上能实现以上操作,且可读性更强。
>>> def square(x):
... return x * x
...
>>> numbers = [8, 4, 6, 5]
>>> [square(num) for num in numbers]
[64, 16, 36, 25]
>>> items = [13, 10, 25, 8]
>>> evens = [num for num in items if num % 2 == 0]
>>> evens
[10, 8]
至于实际中用什么方式,自己选择。
len, max, min 和 sum :计算集中量Python 有几个计算集中量函数,即:将一组值组合成单个结果的函数。这几个函数的应用非常简单,仅举一例:
>>> numbers = [30, 10, 20, 40]
>>> len(numbers)
4
>>> max(numbers)
40
>>> min(numbers)
10
>>> sum(numbers)
100
有三个函数可以接受任何容器数据类型,比如集合、字典甚至字符串:
>>> author = 'guidovanrossum'
>>> len(author)
14
>>> max(author)
'v'
>>> min(author)
'a'
sum 的参数必须是由数字为成员的容器,这意味着,以下操作是可行的:
>>> sum(b'guidovanrossum')
1542
把问题留给你,来弄清楚这是怎么回事?
iter 和 next :迭代iter 和 next 定义了 for 循环的工作机制。
for 循环看起来像这样:
for item in mylist:
print(item)
它的内部实际上是这样做工作的:
mylist_iterable = iter(mylist)
while True:
try:
item = next(mylist_iterable)
print(item)
except StopIteration:
break
Python中的 for 循环是一个巧妙伪装的 while 循环。当遍历列表或任何其他支持迭代的数据类型时,只是意味着它理解 iter 函数,并返回一个“迭代器”对象。
Python 中的迭代器对象做两件事:
next 时,都会产生新的值StopIteration 内置异常。这就是 for 循环的工作原理。
顺便说一下,生成器也遵循迭代器协议:
>>> gen = (x**2 for x in range(1, 4))
>>> next(gen)
1
>>> next(gen)
4
>>> next(gen)
9
>>> next(gen)
Error: StopIteration
未完,待续