python解释器退出时new style class的类属性的__del__方法不会被调用

先看看如下一段代码输出什么:

class A(object):
    def __init__(self):
        print "A init"

    def __del__(self):
        print "A del"


class B(object):
    a = A()
    #def __init__(self, a=A()):
    #    self.a = a

print "test"

输出:

A init
test

就因为这个问题,导致我的一个程序资源泄露了:( 而之前这个程序已经正常运行了半年了,只是某次升级的时候,我顺手把A和B从old style class改成new style class了。

以后切记:不要把资源释放的工作放在__del__方法中,这个方法的会不会被调用、会被调用几次,实在有太多的不确定因素了。python …

more ...

P NP问题理解

P和NP的定义

要理解P和NP问题,让我们首先来看看P和NP的定义:

P: The complexity class of decision problems that can be solved on a deterministic Turing machine in polynomial time.

NP: The complexity class of decision problems that can be solved on a non-deterministic Turing machine in polynomial time

翻译一下就是:

P类问题是指确定型图灵机可以在多项式时间内解决的问题

NP类问题是指非确定型图灵机可以在多项式时间内解决的问题

关键词:确定型/非确定型图灵机、多项式时间 …

more ...

采坑记录:python json不支持int类型key

最近踩了一个很好玩的坑:

在python中将key为int类型的dict通过json.dumps出来之后,再用json.loads转为为dict时,发现原来int类型的key变成了str类型

>>> d={1:2}
>>> dump = json.dumps(d)
>>> d
{1: 2}
>>> dump
'{"1": 2}'
>>> d1 = json.loads(dump)
>>> d1
{u'1': 2}

后来google搜了一下,发现和我踩过同样坑的人还不少:

http://stackoverflow.com/questions/17099556/why-do-int-keys-of-a-python-dict-turn-into-strings-when-using-json-dumps http://stackoverflow.com/questions/1450957/pythons-json-module-converts-int-dictionary-keys-to-strings

more ...

将xfe格式的unicode转化为u00fe格式

python 2.x中的unicode,如果某个字符位于80和ff之间,默认是用单字节表示的:

>>> s=u'··'
>>> s
u'\xb7\xb7'
>>> print "%r" % s
u'\xb7\xb7'

如果想转化\u00b7的格式呢? 正像我在这个问题回答一样,json.dumps可以用来做这个事情:

>>> s=u'··'
>>> json.dumps(s)
'"\\u00b7\\u00b7"'
>>> print json.dumps(s)
"\u00b7\u00b7"
more ...

bash while循环读取其他命令的输出

bash while循环读取其他命令的输出有三种方式:pipehere-string以及process substitution

下面通过三段代码来介绍这三种用法以及其中的坑:假设当前目录下有3个.txt文件,通过看看下面三段代码的输出来理解pipe, here-string和process substitution的不同。

pipe


var=0
find . -type f -name "*.txt" | while read i
do 
     ((var++)) 
done
echo $var

输出:0

解释:管道左右的命令会在单独的进程中运行,因此while循环是在一个subshell中执行的,没有改变原shell中的var变量。

here string


var=0
while read i
do 
    ((var++)) 
done <<< "$(find . -type f -name "*.txt …
more ...

python iterator 和 generator

iterator

iterator是一个概念(或者认为是类型集合),而非某个具体类型,是指实现了如下两个方法的类型:

  1. __iter__() 返回iterator对象本身
  2. next() 返回下一个元素

例如,存在一些属于iterator的类型,但并没有iterator这种类型

>>> l=[]
>>> type(l.__iter__())
<type 'listiterator'>
>>> d={}
>>> type(d.iterkeys())
<type 'dictionary-keyiterator'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
>>> type(d.itervalues())
<type 'dictionary-valueiterator'>

generator

generator属于iterator,因为其实现了__iter__next方法:

>>> type(g)
<type 'generator'>
>>> dir(g)
['__class__ …
more ...

python精美片段之找出list中符合条件的第一个元素

第一种写法

e = None
for i in l:
    if condition(i):
        e = i
        break

缺点:不美观

第二种写法

e = [i for i in l if condition(i)][0]
e = filter(condition, l)[0]

缺点:没有做list非空判断可能异常;效率不高,只需要一个元素,但是遍历了原始list所有元素

第三种写法

e = next((i for i in l if condition(i)), None)
e = next …
more ...

python中创建singleton的方法

名称覆盖


class MyClass(object):
    pass

MyClass = MyClass()

这是最简单粗暴的方法,直接用MyClass对象覆盖了同名的类,这样后面的代码就看不到MyClass类了也就不能继续生成这个类对应的对象了。

保存已经存在的类对象


G_INSTANCES = {}

def get_ins(cls, *args, **kwargs):
    if cls not in G_INSTANCES:
        G_INSTANCES[cls] = cls(*args, **kwargs)
    return G_INSTANCES[cls]

class MyClass(object):
    pass

c1 = get_ins(MyClass)
c2 = get_ins(MyClass)
assert id(c1) == id(c2)

使用全局dict保存已经创建过的类对象,下次创建时如果已经存在直接返回。

使用闭包优化上一个方法


def singleton …
more ...

python print 重定向到文件时编码错误

使用python print的时候经常遇到一个奇怪的问题:

print unicode时,如果unicode包含中文,输出到屏幕时一切正常,但是把屏幕输出重定向到文件时,却报编码错误。错误内容大致如下:

UnicodeEncodeError: 'ascii' codec can\'t encode characters in position
0-1: ordinal not in range(128)

原因是这样的:

  1. 因为你的屏幕显示编码是utf8格式的,所以python知道使用utf8来对unicode进行编码
  2. 重定向到文件时,python并不知道文件格式是什么,所以只能使用默认的ascii来进行编码,而ascii不能对中文进行编码,就会看到前面的异常
  3. 其实不仅仅是编码中文时会遇到异常,只要编码的值超过128(ascii表是使用7位的)都会异常

怎么快速解决这个问题呢?

  1. 在代码中以UTF-8的方式打开文件,然后写文件
  2. print unicode之前,显示按str的来源方式编码,比如utf8。原来的print需要改为print ucontent.encode(‘uft8’)
  3. env …
more ...

问号 ( ? ) 在python正则分组中的用法

非捕获分组 (Non-capturing Groups):

首先是上次文章提到一个非捕获分组的用法:

>>> print a
a123b123b
>>> print re.match(r"a(123)", a).groups()
('123',)
>>> print re.match(r"a(?:123)", a).groups()
()
>>> print re.match(r"a(?:123)", a).group()
a123

非捕获分组,即该分组不记录在最终的groups中,但是还是会匹配的

命名分组 (Named Groups):

>>> print a
a123b123b
>>> print re.match(r"a(?P<namedgroup1>[1-3 …
more ...