这几天查装饰器的资料时,意外发现了stackoverflow上一篇很不错的文章,所以就翻译了过来,权当加深自己的理解。 原网址: How to make a chain of function decorators? 是这样的,有人问了一个问题: 能不能用两个装饰器,像这样 @makebold @makeitalic def say (): return "Hello" 可以返回这种东西: "<b><i>Hello</i></b>" 就是HTML语句。 下面是回答: Decorator基础 Python的函数都是对象 要理解decorators,首先要明白在Python中,函数都是对象。来看一个简单的例子: 把这一点牢记于心,我们很快就会用到它。 Python的函数有另外一个有趣的特性:它们可以在另一个函数的内部定义! 函数引用 你已经知道函数都是对象了。因此,函数 可以赋值给一个变量 可以在另一个函数内部定义 这意味着一个函数可以返回另一个函数。 这不是全部! 如果你可以返回一个函数,这意味着你也可以把函数作为一个参数。 现在,你已经具备了所有理解decorators所需要的知识了。 不难看出,decorators其实就是“包装纸”,这意味着他们可以让你在它们装饰好的函数前后执行你想要的代码,而不用改动函数本身。 自制装饰器 如何手工制作装饰器呢: 现在,你可能希望,每次你调用 a_stand_alone_function 的时候,实际调用的是 a_stand_alone_function_decorated 。这其实很容易,只需要用 my_shiny_new_decorator 返回的函数来覆盖 a_stand_alone_function 。 揭秘decorators 使用decorator语法来实现前面的例子: 这就是全部了,非常简单。 @decorator 其实就是 another_stand_alone_function = my_shiny_new_decorator ( anothe...
注:本文只讨论最大堆排序,最小堆排序同理 一 . 堆 堆(heap)可以定义为一棵 完全 二叉树,并且这棵树的每一个节点都大于或等于它的子女节点。 最大堆长这样子: 堆的特性 一棵n节点的 完全 二叉树,其高度为$$\lfloor \log_{2}n\rfloor$$ 堆的每一个节点都大于等于它的子女节点。 可以用数组来实现堆。留空H[0],然后在H[1]到H[n]中存在堆元素。留空H[0]的目的是为了让之后的堆排序更加的方便。 所有父母节点的键会在数组的前$$\lfloor n/2 \rfloor$$ 个位置中,而叶子节点会占据后面的$$\lceil n/2 \rceil$$个位置。 在数组中,对于每一个位于父母位置i的键来说,它的子女会位于2i和2i+1 对于一个位于位置i的键来说它的父母将会位于$$\lfloor i/2 \rfloor$$ 如何生成堆 自底向上堆构造(bottom-up heap construction): 对每个父母节点进行父母优势检查: 从最后的父母节点开始,到根为止,检查这些节点的键是否满足父母优势要求。 如果该节点不满足,就把该节点的键K与它子女的最大键进行交换。 然后再检查新位置上,K是不是满足父母的优势要求。 效率: 最坏情况下,每个位于树第i层的节点都要移动到树的最底层h,因为移动一层需要两次键值比较,因此移动到h层需要 2(h-i) 次键值比较,所以总键值比较次数为: 自顶向下堆构造(top-down heap construction): 把新的键连续插入到已经预先构造好的堆: 把包含k附加到堆的最后一个叶节点的后面。 拿k与它的父母节点作比较,如果k刚好小于它的父母节点,则算法停止。 否则,交换k和其父母节点的位置 重复2,3步骤直到k不大于它的父母,或者到达了根为止。 效率: 因为包含n个节点的树的高度大约是 log n ,因此每次插入的时间效率属于 O(log n) 总时间效率叠加即可。 二. 堆排序 堆排序的思路很简单: 把数组构造成堆,此时根是最大值。 把根从堆中“移除”,即把...