天天看点

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

sorted

排序算法

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

1

2

<code>&gt;&gt;&gt; </code><code>sorted</code><code>([</code><code>1</code><code>,</code><code>10</code><code>,</code><code>2</code><code>,</code><code>5</code><code>,</code><code>42</code><code>,</code><code>6</code><code>])</code>

<code>[</code><code>1</code><code>, </code><code>2</code><code>, </code><code>5</code><code>, </code><code>6</code><code>, </code><code>10</code><code>, </code><code>42</code><code>]</code>

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

<code>&gt;&gt;&gt; </code><code>sorted</code><code>([</code><code>36</code><code>,</code><code>5</code><code>,</code><code>-</code><code>12</code><code>,</code><code>9</code><code>,</code><code>-</code><code>21</code><code>],key</code><code>=</code><code>abs</code><code>)</code>

<code>[</code><code>5</code><code>, </code><code>9</code><code>, </code><code>-</code><code>12</code><code>, </code><code>-</code><code>21</code><code>, </code><code>36</code><code>]</code>

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

3

<code>list</code> <code>=</code> <code>[</code><code>36</code><code>, </code><code>5</code><code>, </code><code>-</code><code>12</code><code>, </code><code>9</code><code>, </code><code>-</code><code>21</code><code>]</code>

<code>keys </code><code>=</code> <code>[</code><code>36</code><code>, </code><code>5</code><code>,  </code><code>12</code><code>, </code><code>9</code><code>,  </code><code>21</code><code>]</code>

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

<code>keys排序结果 </code><code>=</code><code>&gt; [</code><code>5</code><code>, </code><code>9</code><code>,  </code><code>12</code><code>,  </code><code>21</code><code>, </code><code>36</code><code>] </code>

<code>             </code><code>|  |   |    |   | </code>

<code>最终结果    </code><code>=</code><code>&gt; [</code><code>5</code><code>, </code><code>9</code><code>, </code><code>-</code><code>12</code><code>, </code><code>-</code><code>21</code><code>, </code><code>36</code><code>]</code>

字符排序:

<code>&gt;&gt;&gt; </code><code>sorted</code><code>([</code><code>'bob'</code><code>,</code><code>'about'</code><code>,</code><code>'Zoo'</code><code>,</code><code>'Credit'</code><code>])       </code><code>#根据ASCII的大小比较。</code>

<code>[</code><code>'Credit'</code><code>, </code><code>'Zoo'</code><code>, </code><code>'about'</code><code>, </code><code>'bob'</code><code>]</code>

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

<code>&gt;&gt;&gt; </code><code>sorted</code><code>([</code><code>'bob'</code><code>,</code><code>'about'</code><code>,</code><code>'Zoo'</code><code>,</code><code>'Credit'</code><code>],key</code><code>=</code><code>str</code><code>.lower)</code>

<code>[</code><code>'about'</code><code>, </code><code>'bob'</code><code>, </code><code>'Credit'</code><code>, </code><code>'Zoo'</code><code>]</code>

<code>要进行反向排序,不必改动key函数,可以传入第三个函数</code>

<code>reverse</code><code>=</code><code>True</code><code>:</code>

<code>&gt;&gt;&gt; </code><code>sorted</code><code>([</code><code>'bob'</code><code>,</code><code>'about'</code><code>,</code><code>'Zoo'</code><code>,</code><code>'Credit'</code><code>],key</code><code>=</code><code>str</code><code>.lower,reverse</code><code>=</code><code>True</code><code>)</code>

<code>[</code><code>'Zoo'</code><code>, </code><code>'Credit'</code><code>, </code><code>'bob'</code><code>, </code><code>'about'</code><code>]</code>

<code>L </code><code>=</code> <code>[(</code><code>'Bob'</code><code>, </code><code>75</code><code>), (</code><code>'Adam'</code><code>, </code><code>92</code><code>), (</code><code>'Bart'</code><code>, </code><code>66</code><code>), (</code><code>'Lisa'</code><code>, </code><code>88</code><code>)]</code>

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

<code>&gt;&gt;&gt; L</code><code>=</code><code>[(</code><code>'Bob'</code><code>,</code><code>75</code><code>),(</code><code>'Adam'</code><code>,</code><code>92</code><code>),(</code><code>'Bart'</code><code>,</code><code>66</code><code>),(</code><code>'Lisa'</code><code>,</code><code>88</code><code>)]</code>

<code>&gt;&gt;&gt; </code><code>def</code> <code>by_name(t):</code>

<code>     </code><code>return</code> <code>t[</code><code>0</code><code>].lower()</code>

<code>&gt;&gt;&gt; L2</code><code>=</code><code>sorted</code><code>(L,key</code><code>=</code><code>by_name)</code>

<code>&gt;&gt;&gt; L2</code>

<code>[(</code><code>'Adam'</code><code>, </code><code>92</code><code>), (</code><code>'Bart'</code><code>, </code><code>66</code><code>), (</code><code>'Bob'</code><code>, </code><code>75</code><code>), (</code><code>'Lisa'</code><code>, </code><code>88</code><code>)]</code>

再按成绩从高到低排序:

4

5

6

<code>&gt;&gt;&gt; </code><code>def</code> <code>by_score(t):</code>

<code>     </code><code>return</code> <code>t[</code><code>1</code><code>]</code>

<code>&gt;&gt;&gt; L2</code><code>=</code><code>sorted</code><code>(L,key</code><code>=</code><code>by_score,reverse</code><code>=</code><code>True</code><code>)</code>

<code>[(</code><code>'Adam'</code><code>, </code><code>92</code><code>), (</code><code>'Lisa'</code><code>, </code><code>88</code><code>), (</code><code>'Bob'</code><code>, </code><code>75</code><code>), (</code><code>'Bart'</code><code>, </code><code>66</code><code>)]</code>

返回函数---&gt;函数作为返回值

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

普通情况下的求和函数:

7

<code>&gt;&gt;&gt; </code><code>def</code> <code>calc_sum(</code><code>*</code><code>args):</code>

<code>     </code><code>ax</code><code>=</code><code>0</code> 

<code>     </code><code>for</code> <code>n </code><code>in</code> <code>args:</code>

<code>         </code><code>ax</code><code>=</code><code>ax</code><code>+</code><code>n</code>

<code>     </code><code>return</code> <code>ax</code>

<code>&gt;&gt;&gt; calc_sum(</code><code>1</code><code>,</code><code>2</code><code>,</code><code>3</code><code>,</code><code>5</code><code>,</code><code>4</code><code>)</code>

<code>15</code>

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

8

9

10

11

12

<code>&gt;&gt;&gt; </code><code>def</code> <code>lazy_sum(</code><code>*</code><code>args):</code>

<code>     </code><code>def</code> <code>sum</code><code>():</code>

<code>         </code><code>ax</code><code>=</code><code>0</code>

<code>         </code><code>for</code> <code>n </code><code>in</code> <code>args: </code>

<code>            </code><code>ax</code><code>=</code><code>ax</code><code>+</code><code>n</code>

<code>            </code><code>return</code> <code>ax</code>

<code>      </code><code>return</code> <code>sum</code>

<code>&gt;&gt;&gt; f</code><code>=</code><code>lazy_sum(</code><code>1</code><code>,</code><code>2</code><code>,</code><code>3</code><code>,</code><code>4</code><code>,</code><code>5</code><code>)</code>

<code>&gt;&gt;&gt; f</code>

<code>&lt;function lazy_sum.&lt;</code><code>locals</code><code>&gt;.</code><code>sum</code> <code>at </code><code>0x026BBA08</code>

<code>&gt;&gt;&gt;&gt; f()</code>

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

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

<code>           </code><code>ax</code><code>=</code><code>0</code>

<code>           </code><code>for</code> <code>n </code><code>in</code> <code>args:</code>

<code>              </code><code>ax</code><code>=</code><code>ax</code><code>+</code><code>n</code>

<code>           </code><code>return</code> <code>ax</code>

<code>     </code><code>return</code> <code>sum</code>

<code>&gt;&gt;&gt; f1</code><code>=</code><code>lazy_sum(</code><code>1</code><code>,</code><code>2</code><code>,</code><code>3</code><code>,</code><code>4</code><code>,</code><code>5</code><code>)</code>

<code>&gt;&gt;&gt; f2</code><code>=</code><code>lazy_sum(</code><code>1</code><code>,</code><code>2</code><code>,</code><code>3</code><code>,</code><code>4</code><code>,</code><code>5</code><code>)</code>

<code>&gt;&gt;&gt; f1 </code><code>=</code><code>=</code> <code>f2</code>

<code>False</code>

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

闭包

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

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

<code>&gt;&gt;&gt; </code><code>def</code> <code>count():</code>

<code>     </code><code>fs</code><code>=</code><code>[]</code>

<code>     </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>1</code><code>,</code><code>4</code><code>): </code>

<code>        </code><code>def</code> <code>f():</code>

<code>            </code><code>return</code> <code>i</code><code>*</code><code>i</code>

<code>     </code><code>fs.append(f)</code>

<code>     </code><code>return</code> <code>fs</code>

<code>&gt;&gt;&gt; f1,f2,f3 </code><code>=</code> <code>count()</code>

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

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

<code>&gt;&gt;&gt; f1()</code>

<code>9</code>

<code>&gt;&gt;&gt; f2()</code>

<code>&gt;&gt;&gt; f3()</code>

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

3,因此最终结果为 9 

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

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

<code>     </code><code>def</code> <code>f(j):</code>

<code>          </code><code>def</code> <code>g():</code>

<code>               </code><code>return</code> <code>j</code><code>*</code><code>j</code>

<code>          </code><code>return</code> <code>g</code>

<code>     </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>1</code><code>,</code><code>4</code><code>):</code>

<code>          </code><code>fs.append(f(i))</code>

<code>&gt;&gt;&gt; f1,f2,f3</code><code>=</code><code>count()</code>

<code>1</code>

<code>4</code>

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

<code>          </code><code>return</code> <code>lambda</code> <code>:j</code><code>*</code><code>j</code>

<code>     </code><code>fs </code><code>=</code> <code>[]</code>

<code>1</code><code>&gt;</code>

<code>&gt;&gt; f2()</code>

匿名函数

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

<code>&gt;&gt;&gt; </code><code>list</code><code>(</code><code>map</code><code>(</code><code>lambda</code> <code>x:x</code><code>*</code><code>x,[</code><code>1</code><code>,</code><code>2</code><code>,</code><code>3</code><code>,</code><code>4</code><code>,</code><code>5</code><code>]))</code>

<code>[</code><code>1</code><code>, </code><code>4</code><code>, </code><code>9</code><code>, </code><code>16</code><code>, </code><code>25</code><code>]</code>

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

<code>def</code> <code>f(x):</code>

<code>       </code><code>return</code> <code>x</code><code>*</code><code>x</code>

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

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

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

<code>&gt;&gt;&gt; f</code><code>=</code><code>lambda</code> <code>x:x</code><code>*</code><code>x</code>

<code>&gt;&gt;&gt; f&lt;function &lt;</code><code>lambda</code><code>&gt; at </code><code>0x02C9FD68</code>

<code>&gt;&gt;&gt;&gt; f(</code><code>5</code><code>)</code>

<code>25</code>

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

<code>def</code> <code>bulid(x,y):</code>

<code>      </code><code>return</code> <code>lambda</code><code>: x</code><code>*</code><code>x </code><code>+</code> <code>y</code><code>*</code><code>y</code>

<code></code>

本文转自 nw01f 51CTO博客,原文链接:http://blog.51cto.com/dearch/1762147,如需转载请自行联系原作者