Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Monday, July 5, 2010

Still use singleton? There's another choice in python: Borg design pattern

Few months ago i implemented a db extension for my own python web framework, which supports different database backend. To prevent it from creating multiple instance of db-connection i have chosen singleton design pattern as usual. But after spent some time on google i found another interesting design pattern Borg. It's done this job as good as singleton. Let's take a look of this magical pattern:

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
OK, that's it. Have fun.

Wednesday, July 11, 2007

Wednesday, July 4, 2007

Determining Current Function Name

# use sys._getframe() -- it returns a frame object, whose attribute
# f_code is a code object, whose attribute co_name is the name:
import sys
this_function_name = sys._getframe().f_code.co_name

# the frame and code objects also offer other useful information:
this_line_number = sys._getframe().f_lineno
this_filename = sys._getframe().f_code.co_filename

# also, by calling sys._getframe(1), you can get this information
# for the *caller* of the current function. So you can package
# this functionality up into your own handy functions:
def whoami():
import sys
return sys._getframe(1).f_code.co_name

me = whoami()

# this uses argument 1, because the call to whoami is now frame 0.
# and similarly:
def callersname():
import sys
return sys._getframe(2).f_code.co_name

him = callersname()

Tuesday, June 19, 2007

Python Inner Classes

Why Python has inner classes at all?
class Outer:
def __init__(self):
self.x = 5

class Inner:
def __init__(self):
self.y = 10

if __name__ == '__main__':
outer = Outer()
inner = outer.Inner()
print outer.x
print inner.y
print inner.x

I've been seeing a pattern where I'd like to be able to create nested class hiearchies like this. Usually it's due to containment. For example, let's say I have a Tools class that can hold a bunch of tool classes like Hammer or Sawsall. Now, I'd like my tool classes to be able to get back at their containing Tools instance. I generally model these classes like this:

class Tools:
def __init__(self):
self.tools = []

def add(tool):
self.tools.append(tool)

class Hammer:
def __init__(self, tools):
self.tools = tools

class Sawsall:
def __init__(self, tools):
self.tools = tools

Okay, so you can see the pattern, right? Each tool class is going to have this tools argument that tells them who their container is. But this doesn't seem right to me. That the tool classes need reference to their container shouldn't have to bother the person using these classes. It seems a bit weird that I would create an Sawsall instance passing a reference to the container I plan to add it to.

tools = Tools()
sawsall = Sawsall(tools)
tools.add(sawsall)

It just looks redundant. Here's how I would like that to read:

tools = Tools
sawsall = tools.Hammer()
tools.add(sawsall)

Now, that's still a little redundant and doesn't seem entirely correct for some reason but I think the container.Class() convention is more clear than the other way. Even without inner classes, we can still get this functionality by adding a Hammer() method to the Tools class:

class Tools:
def Hammer(self):
return Hammer(self)

Tuesday, June 5, 2007

split String into Chinese Symbol and English Word.

From Huang, Jiahua

# _zhstr , _asstr 存储 中文,非中文 数组
_zhstr = []
_asstr = []
def _fenzhas(stri):
''' 分开中文和非中文,
存入全局数组 _zhstr , _asstr
'''
global _asstr
global _zhstr
ln = len(stri)
_zhstr = []
_asstr = []
n = 0
m = 0
try:
stri[n] >= u'\u4e00'
except:
return 0
while n < ln:
if stri[n] >= u'\u4e00':
if m==0:_zhstr.append(' ')
_zhstr.append(stri[n])
## print 'z:',stri[n]
m=1
else:
if m==1:_asstr.append(' ')
_asstr.append(stri[n])
## print 'a:',stri[n]
m=2
n+=1

Converter CJK Encoding to Unicode

encc = ""
def zh2unicode(stri):
"""Auto converter encodings to unicode

It will test utf8,gbk,big5,jp,kr to converter"""
global encc
for c in ('utf-8', 'gbk', 'big5', 'jp', 'euc_kr','utf16','utf32'):
encc = c
try:
return stri.decode(c)
except:
pass
encc = 'unk'
return stri

Wednesday, May 30, 2007

中文分词模块 from Huang Jiahua

#!/usr/bin/python

# -*- coding: UTF-8 -*-
# Author: Huang Jiahua
# Last modified: 2004-08-25

__revision__ = '0.1'

#切分关键字,要求预先转换为 Unicode 类型
# 分开中文,非中文 -> 按 seps 列表分隔 -> 对中文二元分词 -> 合并 -> 返回数组

import sys
##sys.setappdefaultencoding('utf8')

#分隔关键字列表 seps 设置
seps=[]
seps=[" ","\t","\n","\r",",","<",">","?","!",
";","\#",":",".","'",'"',"(",")","{","}","[","]","|","_","=",
" ",",","?","。","、",""",""","《","》","[","]","!","(",")"]
# Unicode 编码的分隔关键字列表
def _utuni(strr):return unicode(strr,'utf8')
seps=map(_utuni,seps)

##_alkeys={}
_zhkeys={}
_askeys={}
# _zhstr , _asstr 存储 中文,非中文 数组
_zhstr = []
_asstr = []

def _zhsplitkey(stri):
# 对 stri 二元分词法
#存入全局字典 _zhkeys
global _zhkeys
ln = len(stri)
if ln == 1:
return stri
#拆分中文关键字,二元分词法
n = 0
while n < ln-1:
_zhkeys[stri[n]+stri[n+1]] = ''
n = n+1
## return keyy.keys()

def _fenzhas(stri):
# 分开中文和非中文,
# 存入全局数组 _zhstr , _asstr
global _asstr
global _zhstr
ln = len(stri)
_zhstr = []
_asstr = []
n = 0
m = 0
try:
stri[n] >= u'\u4e00'
except:
return 0

while n < ln:
if stri[n] >= u'\u4e00':
if m==0:_zhstr.append(' ')
_zhstr.append(stri[n])
## print 'z:',stri[n]
m=1
else:
if m==1:_asstr.append(' ')
_asstr.append(stri[n])
## print 'a:',stri[n]
m=2
n+=1
## print 'zh:',''.join(_zhstr)
## print 'as:',''.join(_asstr)

def _fenseps(stri):
# 按 seps 列表分隔, 返回分隔后数组
global seps
alkeys={}
n = 0
m = 0
ln=stri.__len__()
while n if stri[n] in seps:
alkeys[stri[m:n]]=''
m=n+1
n+=1
if n>m:alkeys[stri[m:n]]=''
return alkeys.keys()

def splitkey(stri):
"""Split the keys

Split the keys."""
# 接受 str 返回分词后数组
global _zhstr
global _asstr
global _zhkeys
global _askeys
_zhkeys = {}
_askeys = {}
_zhstr = []
_asstr = []
_fenzhas(stri) #分开中文,非中文,存入数组 _zhstr , _asstr
zhstr= _fenseps(''.join(_zhstr))
asstr= _fenseps(''.join(_asstr)) #?
_zhstr = []
_asstr = []
for i in zhstr:
_zhsplitkey(i) #中文分词放入字典 _zhkeys
for i in asstr:
_askeys[i]=''

alkeys = {}
alkeys.update(_zhkeys)
alkeys.update(_askeys)
_zhkeys = {}
_askeys = {}
return alkeys.keys()

if __name__=="__main__":
# 命令行测试
import sys
# sys.setappdefaultencoding('unicode')
enc = sys.stdin.encoding
if len(sys.argv) > 1:
keyy = sys.argv[1]
else:
keyy = sys.stdin.read()
## keyyy = splitkey(keyy.decode(enc))
keyyy = splitkey(keyy.decode('utf8'))
for i in keyyy:
## print i.encode(enc),
print i.encode('utf8'),

Tuesday, May 22, 2007

MixIn

MixIn 技术 (感谢 limdou 的介绍)

def MixIn(pyClass, mixInClass):
print "Mix class:",mixInClass, " into: ",pyClass,'\n'
pyClass.__bases__ += (mixInClass,)

class A:
def __init__(self):
self.name = "Class A"
def fun(self):
print self.name

class B:
def __init__(self):
self.name = "Class B"
def add(self, a,b):
print 'function defined in B'
return a + b

obj_a = A()

print obj_a
print dir(obj_a),'\n'

MixIn(A,B)

print obj_a
print dir(obj_a),'\n'

print obj_a.add(3,5)


-----------------------------------------〉
执行结果:

>>>
<__main__.a>
['__doc__', '__init__', '__module__', 'fun', 'name']

Mix class: __main__.B into: __main__.A

<__main__.a>
['__doc__', '__init__', '__module__', 'add', 'fun', 'name']

function defined in B
8

解释一下 MixIn 技术,就是使 一个类成为另一个类的基类, 这样会使 被 MixIn 的那个类具有了新的特性。
在例子程序中, 我们将 B 类 MixIn 进 A 类, 成为 A 的基类,于是, A 类的实例便具有了 B 类的方法(add)


obj_a = A() obj_a 是 类 A 的一个实例

print obj_a <__main__.a>
print dir(obj_a),'\n' ['__doc__', '__init__', '__module__', 'fun', 'name']

MixIn(A,B) 将B MixIn 进 A

print obj_a <__main__.a>

print dir(obj_a),'\n' ['__doc__', '__init__', '__module__', 'add', 'fun', 'name']
注意,这时候,多了一个 add 方法(类B 中定义)

print obj_a.add(3,5) 现在 A 的实例可以使用 B 中的方法了

python中实现Single模式

#!/usr/bin/env python

#-*- coding:utf-8 -*-

class Singleton:

""" A python singleton """

class __impl:

""" Implementation of the singleton interface """

def spam(self):

""" Test method, return singleton id """

return id(Singleton.__instance)

# storage for the instance reference

__instance = None

def __init__(self):

""" Create singleton instance """

# Check whether we already have an instance

if Singleton.__instance is None:

# Create and remember instance

Singleton.__instance = Singleton.__impl()

# Store instance reference as the only member in the handle

self.__dict__['_Singleton__instance'] = Singleton.__instance

def __getattr__(self, attr):

""" Delegate access to implementation """

return getattr(self.__instance, attr)

def __setattr__(self, attr, value):

""" Delegate access to implementation """

return setattr(self.__instance, attr, value)

class SingletonType(type):

"""Singleton Metaclass"""

def __init__(cls, name, bases, dic):

super(SingletonType, cls).__init__(name, bases, dic)

cls.instance = None

def __call__(cls, *args, **kwargs):

if cls.instance is None:

cls.instance = super(SingletonType, cls).__call__(*args, **kwargs)

return cls.instance

class MyClass:

__metaclass__ = SingletonType

if __name__ == '__main__':

#print dir(MyClass)

ob1 = MyClass()

ob2 = MyClass()

print id(ob1), id(ob2)

#print dir(Singleton)

s1 = Singleton()

s2 = Singleton()

print id(s1), s1.spam()

print id(s2), s2.spam()

Tuesday, May 15, 2007

map(), filter(), reduce()

for 语句一样,内置函数 map(), filter(), 和 reduce() 都是对一个序列的每一个元素执行一定的操作。这三个函数的第一个参数都是一个函数,而后续 参数都是一些序列。http://wiki.woodpecker.org.cn/moin/TPiP/AppendixA

1.map() 函数返回一个与输入序列长度相同的列表,其中每一个元素都是对 输入序列中相应位置的元素的转换的结果。

如果传给 map() 的函数参数接受多个参数,那么就可以给 map 传递多个序列。如果这些传进来的序列长度不一, 那就在短的序列后面补 None。函数参数还可以是 None , 这样的话就会用序列参数中的元素生成一个元组的序列。

2.filter() 函数返回的是输入序列中满足一定条件的元素组成的序列, 这个条件由传递给 filter() 的函数参数决定。该函数参数必须接受 一个参数,它的返回值会被当作布尔值处理。

3.reduce() 函数的第一个参数是个函数,该函数必须接受两个参数。 它的第二个参数是一个序列,reduce() 函数还可以接受可选的第三个参数作为初始值。 对于输入序列中每一个元素,reduce() 将前面的累计结果与该元素结合起来, 直到序列的末尾。reduce() 的效果——就像 map()filter() 一样—— 和循环类似,也是对序列中每一个元素执行操作,它的主要目的是产生某种累计结果, 累加,或是在许多不确定的元素中进行选择。

4.List comprehension (listcomps) 是一种由 python2.0 引入的语法形式。根据输入序列产生一个列表。list comprehension 是由以下部分组成:(1) 两端的方括号 (就像构造列表的语法一样,其实它就是在构造一个列表)。(2) 一个表达式,它 通常包含一些在 for 子句被绑定的名字。(3) 一个或多个 for 子句, 它们循环地对名字进行绑定 (就像 for 循环那样)。(4) 零或多个 if 子句,用来 对结果进行限制。通常 if 子句也包含一些在 for 子句中被绑定的名字。其中for 子句中绑定的名字在它外部的(或是全局的,如果名字是这么定义的话)作用范围内仍然有效。eg:

1 >>> [(n,c) for n in (95,100,105) for c in 'aei' if ord(c)>n]
2 [(95, 'a'), (95, 'e'), (95, 'i'), (100, 'e'), (100, 'i')]