飞污熊博客

静下心来做一件事

python有着强大的表达式语法和函数特性,其中一个我的最爱便是装饰器。 在设计模式中,装饰器能够在不使用子类的情况下动态的修改函数、方法或类的功能。

当你需要扩展某个函数的功能却不想直接修改这个函数的时候,装饰器就可以派上用场了。 实现装饰器模式有很多种方法,但是python通过强大的语法支持来让这个变得相当容易。

在这篇文章中我将深入讲解Python的函数装饰器,并通过一系列的源码示例来彻底讲清楚这个东西。 所有例子都在Python2.7下运行通过,不过只需要稍作改变就可以运行在Python3上了, 甚至我猜测什么都不用改变都可以的,读者可以自己去试试。

本质上来讲,装饰器是以包装器形式工作的,其实就是在执行目标函数之前或之后加入自己的逻辑, 而不需要改变目标函数本身就可以增强它的功能,也就是说装饰了它。

阅读全文 »

在讲生成器之前,先讲讲python里面常用的几个常见的推导式:

列表推导式(list comprehension)

1
my_list = [f(x) for x in sequence if cond(x)]

字典推导式(dictionary comprehension)

1
my_dict = {k(x): v(x) for x in sequence if cond(x)}

集合推导式(set comprehension)

1
my_set = {f(x) for x in sequence if cond(x)}

生成器表达式(generator expression)

1
my_generator = (f(x) for x in sequence if cond(x))

对于大部分的python初学者而言,生成器和yield关键字比较难以理解。很多文章解释的不清楚, 这篇文章我想深入的讲解这个yield关键字,它到底是个什么东西,为什么它如此的重要,以及我们该如何去使用它。

注意:近些年来,随着越来越多的特性被加入到PEP中,生成器变得越来越强大。我在下一篇文章会深入讲解协程、多任务协作和异步I/O这些高阶知识,来见识下yield 的威力。

阅读全文 »

迭代(iteration)指的是去获取元素的一种方式,一个接一个。当你显式或隐式的使用循环来遍历某个元素集的时候,那就是迭代。

在Python里面,可迭代对象(iterable)和迭代器(iterator)有着特殊的含义。

  • iterable是实现了__iter__()方法的对象,该方法会返回一个iterator对象
  • iterator是实现了__iter__()__next__()方法的对象,__iter__()方法返回的是iterator对象本身

由此可见,iterableiterator的本质区别就是后者多了一个__next__()方法。 也就是说一个iterator对象必定是一个iterable对象。

阅读全文 »

模块和包都是用来组织代码用的,在python中一个模块就是一个.py文件,而一个包就是一个包含了__init__.py的文件夹。 使用模块最大的好处就是提高代码可维护性,我们在编写代码的时候通常会引用内置模块或第三方模块。

引入包是为了解决命名冲突问题,你可以把包当成是命名空间,比如你写的abc.py模块和其他人写的abc.py模块只要在不同的包中就不会冲突。 只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。

阅读全文 »

字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题。

Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode标准也在不断发展, 但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。

现在,捋一捋ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节。

但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。

阅读全文 »

函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量(或者说不能给变量重新赋值), 因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言, 由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。

函数式编程(请注意多了一个”式”字)——Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。 它的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

阅读全文 »

操作系统:CentOS 6.5_x86_64

前提:提前准备好编译环境,防火墙和selinux都关闭

主机IP:两台机器,192.168.203.103、192.168.203.104

安装软件:jdk-8u51-linux-x64, apache-tomcat-8.0.24, tomcat-connectors-1.2.41, httpd-2.2.15, httpd-devel-2.2.15

阅读全文 »

纯归并排序的复杂度为O(nlgn),而纯插入排序的时间复杂度为O(n^2)。数据量很大的时候采用归并排序。

但是在n较小的时候插入排序可能运行的会更快点。因此在归并排序中当子问题变得足够小时, 采用插入排序来使得递归的叶子变粗可以加快排序速度。那么这个足够小到底怎么去衡量呢? 请看下面:

这么几个我不证明了,比较简单:

  • 插入排序最坏情况下可以在O(nk)时间内排序每个长度为k的n/k个子列表
  • 在最坏情况下可在O(nlg(n/k))的时间内合并这些子表
  • 修订后的算法的最坏情况运行时间复杂度是O(nk + nlg(n/k))

那么,O(nk+nlg(n/k))=O(nlgn).只能最大是k=O(lgn).等式左边中第一项是高阶项。 k如果大于lgn,则比归并排序复杂度大了。 左边可以写成nk+nlgn-nlgk,k等于lgn时,就是2nlgn-nlglgn.忽略恒定系数,则与归并排序是一样的。 最后结论: k < lg(n)的时候,使用插入排序。

阅读全文 »

我们不仅要知其然,而且要知其所以然,所以先给大家准备一些理论知识课,这样对以后的应用将会事半功倍。

1、什么是LVS?

请阅读作者章文嵩博士自己的研究报告,共计4部分,看完后对集群和LVS就有了初步的了解,不懂时可以翻翻。

阅读全文 »