据廖雪峰python3教程----python学习第十一天

sorted


排序算法

     Python的内置sorted()函数可以对list进行排序:

1
2
>>> sorted([1,10,2,5,42,6])
[12561042]

此外,sorted()函数也是一个高阶函数,他还可以接受一个key函数来实现自定义的排序,例如按绝对值大小排序:

1
2
>>> sorted([36,5,-12,9,-21],key=abs)
[59-12-2136]

key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。对比原始的list和进过key=abs 处理的list:

1
2
3
list = [365-129-21]
 
keys = [365,  129,  21]

然后sorted()函数按照keys进行排序,并按照对应关系返回list相应的元素:


1
2
3
keys排序结果 => [59,  12,  2136
             |  |   |    |   | 
最终结果    => [59-12-2136]

字符排序:

1
2
>>> sorted(['bob','about','Zoo','Credit'])       #根据ASCII的大小比较。
['Credit''Zoo''about''bob']

忽略大小写的字符串排序:

1
2
>>> sorted(['bob','about','Zoo','Credit'],key=str.lower)
['about''bob''Credit''Zoo']
1
2
要进行反向排序,不必改动key函数,可以传入第三个函数
reverse=True:
1
2
>>> sorted(['bob','about','Zoo','Credit'],key=str.lower,reverse=True)
['Zoo''Credit''bob''about']


1
= [('Bob'75), ('Adam'92), ('Bart'66), ('Lisa'88)]


请用sorted()对上述列表分别按名字排序:

1
2
3
>>> L=[('Bob',75),('Adam',92),('Bart',66),('Lisa',88)]
>>> def by_name(t):
     return t[0].lower()
1
2
3
>>> L2=sorted(L,key=by_name)
>>> L2
[('Adam'92), ('Bart'66), ('Bob'75), ('Lisa'88)]



再按成绩从高到低排序:

1
2
3
4
5
6
>>> L=[('Bob',75),('Adam',92),('Bart',66),('Lisa',88)]
>>> def by_score(t):
     return t[1]
>>> L2=sorted(L,key=by_score,reverse=True)
>>> L2
[('Adam'92), ('Lisa'88), ('Bob'75), ('Bart'66)]


返回函数--->函数作为返回值


高阶函数除了可以接受函数作为参数外,还可以把函数作为结果返回。

普通情况下的求和函数:

1
2
3
4
5
6
7
>>> def calc_sum(*args):
     ax=0 
     for in args:
         ax=ax+n
     return ax
>>> calc_sum(1,2,3,5,4)
15

把函数作为返回值。( 如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数: )

1
2
3
4
5
6
7
8
9
10
11
12
>>> def lazy_sum(*args):
     def sum():
         ax=0
         for in args: 
            ax=ax+n
            return ax
      return sum
>>> f=lazy_sum(1,2,3,4,5)
>>> f
<function lazy_sum.<locals>.sum at 0x026BBA08
>>>> f()
15


在上面的例子中,在函数 lazy_sum 中有定义了函数 sum ,并且,内部函数 sum 可以引用外部函数 lazy_sum 的参数和局部变量,当 laizy_sum 返回函数 sum 时, 相关参数和变量都保存在返回的函数中,这种称为 ‘闭包(Closure)’的程序结构拥有极大的威力。


当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:

1
2
3
4
5
6
7
8
9
10
11
>>> def lazy_sum(*args):
     def sum():
           ax=0
           for in args:
              ax=ax+n
           return ax
     return sum
>>> f1=lazy_sum(1,2,3,4,5)
>>> f2=lazy_sum(1,2,3,4,5)
>>> f1 == f2
False


f1()和 f2()的调用结果互不影响。



闭包


注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。


另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:

1
2
3
4
5
6
7
8
>>> def count():
     fs=[]
     for in range(1,4): 
        def f():
            return i*i
     fs.append(f)
     return fs
>>> f1,f2,f3 = count()

每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。

调用f1( ),f2( )和f3( )的结果应该是1,4,9,但实际:

1
2
3
4
5
6
>>> f1()
9
>>> f2()
9
>>> f3()
9


结果全部都是9,原因在于返回的函数引用了变量 i ,但它并非立刻执行。等到3个函数都返回是,它们所引用的变量 i 应经变成了

3,因此最终结果为 9 

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法就是在创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何改变更改,已绑定到函数参数的值不变:

1
2
3
4
5
6
7
8
9
>>> def count():
     def f(j):
          def g():
               return j*j
          return g
     fs=[]
     for in range(1,4):
          fs.append(f(i))
     return fs
1
2
3
4
5
6
7
>>> f1,f2,f3=count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

缺点就是 代码较长,可以利用lambda 函数缩短代码:

1
2
3
4
5
6
7
>>> def count():
     def f(j):
          return lambda :j*j
     fs = []
     for in range(1,4):
          fs.append(f(i))
     return fs
1
2
3
4
5
6
7
>>> f1,f2,f3=count()
>>> f1()
1>
>> f2()
4
>>> f3()
9


匿名函数


在Python中,对匿名函数提供了有限支持。还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外,还可以直接传入匿名函数:

1
2
>>> list(map(lambda x:x*x,[1,2,3,4,5]))
[1491625]

 

通过例子可以看出匿名函数 lambda x:x*x实际上就是:

1
2
def f(x):
       return x*x

关键字lambda表示匿名函数,冒号前面的x表示函数参数

匿名函数有个限制,就是只能有一个表达式,不用写return,表达式的值就是return

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外。匿名函数也是一个函数对象,也可以吧匿名函数赋值给一个变量,再利用变量来调用这个函数:

1
2
3
4
>>> f=lambda x:x*x
>>> f<function <lambda> at 0x02C9FD68
>>>> f(5)
25

同样也可以把匿名函数作为函数的返回值:

1
2
def bulid(x,y):
      return lambda: x*+ y*y




本文转自 nw01f 51CTO博客,原文链接:http://blog.51cto.com/dearch/1762147,如需转载请自行联系原作者
上一篇:【Java入门提高篇】Day28 Java容器类详解(十)LinkedHashMap详解


下一篇:藏在高端智能手机芯片里的“外交官”:射频前端