文章目录
sorted(iterables, key=lambda, reverse=False)
普通的sorted(iterables)可将list类对象升序排列,如list类对象为多要素对象,则默认根据第一个要素进行排序;
如设reverse可选参数为True,则会降序排列;
在sorted函数可选参数key参数中写入lambda函数类似于一种模拟排列,即通过lambda函数转换原iterables中的元素,对转换后的元素进行排列,并返回该虚拟排列对应的原iterables元素的映射排列
>>> import collections
>>> a = collections.Counter(['a','a','b','c','d','d','d'])
>>> a
Counter({'d': 3, 'a': 2, 'b': 1, 'c': 1})
>>> sorted(a.items(), key=lambda x: x[0])
[('a', 2), ('b', 1), ('c', 1), ('d', 3)]
>>> sorted(a.items(), key=lambda x: x[1])
[('b', 1), ('c', 1), ('a', 2), ('d', 3)]
注意以上a作为一个dict类的对象,dict类对象无顺序因此不可排序,因此选用了.items()方法,该方法将dict类对象转换成list类对象,该对象的每个要素均为原dict类对象的key和value组成的tuple。上代码分别表示以要素第一位置元素排列和第二位置元素排列后的原iterables的元素位置
>>> list1 = [3,5,-4,-1,0,-2,-6]
>>> sorted(list1, key=lambda x: abs(x))
[0, -1, -2, 3, -4, 5, -6]
zip(a, b, …)
zip函数将其输入的多个iterables按照各自的index位置进行拆解后将相同位置的要素重组为tuple,返回一个含有多tuple的zip对象;如不同的iterable要素长度或类型不同,重组时将以最短的那个为标准
>>> list(zip([1,2],[2,3],[3,4]))
[(1, 2, 3), (2, 3, 4)]
>>> list(zip([1,2],[2,3],[3,4,5]))
[(1, 2, 3), (2, 3, 4)]
>>> list(zip([1],[2,3],[3,4,5]))
[(1, 2, 3)]
>>> list(zip([(1)],[2,3],[3,4,5]))
[(1, 2, 3)]
>>> list(zip([[(1)],],[2,3],[3,4,5]))
[([1], 2, 3)]
zip(*c)可以将已经拆分重组的tuple list恢复为之前的组合状态,但是恢复后的各个元素均为tuple
>>> d=zip([1,2],[2,3],[3,4])
>>> list(zip(*d))
[(1, 2), (2, 3), (3, 4)]
作用域
模块对应作用域是global,内层作用域为local,外层作用域为nonlocal。变量查找顺序为:local -> nonlocal -> global -> builtin。
只有class、def和lamda会创建作用域,if,for等语句内部并不会形成local作用域。python读取变量的时候,如果local作用域没有该变量,则逐级查找外层的nonlocal作用域,如仍没有,则查找global作用域。在global定义变量时,如果没有指明nonlocal或global, 就是在局部作用域定义一个新的变量;当有多层嵌套时nonlocal声明优先指向最内层的nonlocal作用域。
>>> b = 2
def nonlocal_func():
b = 22
def local_func():
global b
print(b)
return local_func
>>> nonlocal_func()()
2
>>> def nonlocal_func():
b = 22
def local_func():
b = 222
def local_local_func():
nonlocal b
print(b)
return local_local_func
return local_func
>>> nonlocal_func()()()
222
闭包(closure或lexical closure)
通常而言,由class、def和lambda创造的局部作用域内的变量在其相应的外层作用域是无法访问的,变量访问近能自内而外,而不能自外而内,如下所示:
>>> a1 = 1
>>> def func():
a2 = 2
print(a1)
>>> a2
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'a2' is not defined
>>> func()
1
而闭包则是一种特殊现象,即局部作用域中的变量参数输入在闭包中实现某种程度的存储。可以认为在闭包中,方法和数据实现了一定程度的封装,或者说将数据封装进了方法之中,这本质上与类是相似的。
由于仅有class、def和lambda可以创建局部作用域,那么他们都可以实现闭包的效果,而class本身就是更为高级的封装,而所有的lambda实现均可以通过def实现,因此下面以lambda为例示意闭包的效果:
>>> def wrapper(a, b):
return lambda x: x * a + b
>>> y = wrapper(1,2)
>>> y
<function wrapper.<locals>.<lambda> at 0x00000248EA95BBF8>
在wrapper函数内部定义lambda函数时lambda函数便形成了一个闭包。正常而言参数a和b都在局部作用域中,外部无法调用和访问,只能通过调用wrapper函数而对a和b进行传参。将wrapper函数赋给y后,y变成了一个函数
>>> y(1)
3
>>> y(2)
4
>>> y(3)
5
可见对于y的调用传参相当于仅传入了不同的x值,而a和b的值已经在将wrapper赋给y的时候固化进了y之中。因此局部作用域中的参数实现了在外部的存储。a和b此时被称为自由变量。自由变量即使在其所处局部作用域函数的生命周期结束以后依然存在(但不可调用),因为它被闭包引用了,所以不会被回收。
可用def转写上面的例子:
>>> def wrapper(a,b):
def closure(x):
return x * a + b
return closure
>>> y = wrapper(2,3)
>>> y(1)
5
>>> y(2)
7
闭包closure可以被理解为一个只读的对象,你可以通过外层函数wrapper给其传递属性,如wrapper(2,3),闭包提供给你一个执行的接口。通常在程序中,闭包可帮助我们完成一些通用的功能。