2010年7月19日星期一

Http之Get/Post请求区别

1.HTTP请求格式:



[]
在HTTP请求中,第一行必须是一个请求行(request line),用来说明请求类型、要访问的资源以及使用的HTTP版本。紧接着是一个首部(header)小节,用来说明服务器要使用的附加信息。在首部之后是一个空行,再此之后可以添加任意的其他数据[称之为主体(body)]。
2.GET与POST区别
HTTP定义了与服务器交互的不同方法,最基本的方法是 GET 和 POST.
HTTP-GET和HTTP-POST是使用HTTP的标准协议动词,用于编码和传送变量名/变量值对参数,并且使用相关的请求语义。每个HTTP-GET和HTTP-POST都由一系列HTTP请求头组成,这些请求头定义了客户端从服务器请求了什么,而响应则是由一系列HTTP应答头和应答数据组成,如果请求成功则返回应答。
  HTTP-GET以使用MIME类型application/x-www-form-urlencoded的urlencoded文本的格式传递参数。Urlencoding是一种字符编码,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。附加参数还能被认为是一个查询字符串。
  与HTTP-GET类似,HTTP-POST参数也是被URL编码的。然而,变量名/变量值不作为URL的一部分被传送,而是放在实际的HTTP请求消息内部被传送。
(1)get是从服务器上获取数据,post是向服务器传送数据。
(1) 在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交。
(2) 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
(2) GET方式提交的数据最多只能有1024字节,而POST则没有此限制。
(3) 安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。
注:所谓安全的意味着该操作用于获取信息而非修改信息。幂等的意味着对同一 URL 的多个请求应该返回同样的结果。完整的定义并不像看起来那样严格。换句话说,GET 请求一般不应产生副作用。从根本上讲,其目标是当用户打开一个链接时,她可以确信从自身的角度来看没有改变资源。比如,新闻站点的头版不断更新。虽然第二次请求会返回不同的一批新闻,该操作仍然被认为是安全的和幂等的,因为它总是返回当前的新闻。反之亦然。POST 请求就不那么轻松了。POST 表示可能改变服务器上的资源的请求。仍然以新闻站点为例,读者对文章的注解应该通过 POST 请求实现,因为在注解提交之后站点已经不同了(比方说文章下面出现一条注解)。
下面举一个简单的例子来说明它们的区别:











<% If Request.QueryString("Text") <> "" Then %>
通过get方式传递的字符串是: "<%= Request.QueryString("Text") %>"

<% End If %>
<% If Request.Form("Text") <> "" Then %>
通过Post方式传递的字符串是: "<%= Request.Form("Text") %>"

<% End If %>


转载自:
http://www.cnblogs.com/wxf0701/archive/2008/08/17/1269798.html

2010年7月6日星期二

python 读取SQLite数据库所有表的定义(原创)

from sqlite3 import dbapi2 as sqlite
import re
p=re.compile("\(u(\'\w+\'),\)")

con = sqlite.connect("trac.db")

cur = con.cursor()
cur.execute("select name from sqlite_master where type='table'")
ticol = cur.fetchall()
for i in range (0,len(ticol)):
sqlstr=' '.join(["select * from sqlite_master where type='table'","and name =", p.match(str(ticol[i])).group(1)])

cur.execute(sqlstr)
stu = cur.fetchone()





f = file("table.txt","a")
f.write(str(i+1))
f.write( ': ')
for j in range(0,len(stu)):



f.write(str(stu[j]))
f.write('\n')
else:
f.write('-------------------------------------\n')
f.close()

cur.close()

2010年7月1日星期四

富士康主要生产线将迁廊坊 是福是祸?

富士康有关发言人昨天表示,为缓解劳动力成本上升压力,富士康将把主要生产线由深圳迁往河北廊坊。这是富士康首次承认将大规模内迁。

  笔者在众多的评论中看到大多是声讨之音,仔细想想,觉得应该是一件好事,是一个多赢的局面。

  1、 有利于内地城市的发展,尤其是二线城市。带动十多万人的就业,不知道会不会增加当地税收;提高内地企业的管理水平,为以后的发展打基础。内地很多政府领导根本就不懂得怎么发展,假、大、空一直是他们的代名词,应该是实干的时候了。但不要忘了疏导,有利于社会发展和人类生存是根本。

  2、 有利于员工。工资待遇和深圳持平,消费水平又低于深圳,相当于增加收入;不用外出打工,有家庭安全感,在情感上不在孤寂。

  3、 有利于富士康公司。花同样的费用甚至更低些,能获取更多的利润,又解决了员工孤独寂寞导致的极端事件,何乐而不为。

  4、 有利于深圳发展。个人感觉深圳已经落后于长三角了,和上海的差距越来越大,代工厂已经成为深圳的负担,在代工、模仿、抄袭之后,应该真正研发自己的产品了,掌握完整的产业链,摆脱低端生产。

  5、 有利于两岸关系的深入发展。这些大企业应该是连接两岸最直接的纽带,企业的老大肯定会游走于两岸政府之间,促进两岸和平,最终合而为一。

转载自:
http://news.cnfol.com/100702/101,1609,7955680,00.shtml

2010年6月30日星期三

ClearSilver

1. 什么是ClearSilver

Clearsilver is a fast, powerful, and language-neutral HTML template system. In both static content sites and dynamic HTML applications, it provides a separation between presentation code and application logic which makes working with your project easier. The design of Clearsilver began in 1999, and evolved during its use at onelist.com, egroups.com, and Yahoo! Groups. Today many other projects and websites using it.
2. 为什么使用ClearSilver

High Performance and Language Neutral. Because Clearsilver is written as a C-library, and exported to scripting languages like Python, Perl, Java and Ruby via modules, it is extremely fast. This also means you can work with the same template system independent of the language your project is in.
Pluggable Look and Feel. Clearsilver makes it easy to face lift a site by providing a new set of templates. It is possible to easily run more than one look and feel at once, and share components with a base look and feel to reduce maintenance.
Internationalization Support. Clearsilver makes it trivial to support internationlization. You write your templates in your native language and included tools automatically extract and catalog language strings for translation.
Advanced features. Built in support for advanced features such as gzip compression, smart whitespace stripping, parametric macros, online debugging mode, url and javascript string escaping, and more.
3. 文档

http://www.clearsilver.net/docs/

4. 下载

http://www.clearsilver.net/downloads/

5. 教程

一切从Hello World开始

::-- ZoomQuiet [2005-08-23 03:52:16]

5.1. 快速体验

clearsilver是一个高性能的模版系统,让我们看看他的使用网站,就知道他的表现有多好。

Bloglines
Google Groups
Yahoo Groups
其他的应用请到这里http://www.clearsilver.net/examples.hdf

clearsilver由3各部分组成:hdf数据描述,cst模版文件,py逻辑处理向hdf赋值



编写hdf文件:hello.hdf

# This is my static data for Hello World (and this is a comment)

Hello = Hello World!

WeekDays {
0 = Sunday
1 = Monday
2 = Tuesday
3 = Wednesday
4 = Thursday
5 = Friday
6 = Saturday
}
编写模版文件:hello.cst






On ,




On ,



Hey ,
这个模版文件唯一要注意的就是cs if:?Query.day,是用来处理链接参数的:cgi-bin/hello.py?day=1

模版语法详见: http://www.clearsilver.net/docs/

然后将这两部分合二为一:

切换行号显示
1 #!/usr/bin/python
2 #
3 # Hello World using the ClearSilver CGI Kit and Python
4
5 import neo_cgi
6
7 # create a CGI handler context
8 ncgi = neo_cgi.CGI()
9
10 # parse the form data (and post upload data)
11 ncgi.parse()
12
13 # Load our static data
14 ncgi.hdf.readFile("hello.hdf")
15
16 ncgi.display("hello.cst")
17
P.S: 测试环境winXP+IIS5(懒得装apache了)

6. 讨论

感觉clesarsilver很像zope的dtml,都有循环、判断语句什么的。 --tomz
因为都是模版系统,所以肯定有类似的地方,clesarsilver的优势在于:语言无关,性能好,模版语言丰富,逻辑界面分离。--清风

转载自:
http://wiki.woodpecker.org.cn/moin/ClearSilver

软件配置管理工具CVS vs. STARTEAM

CVS 是开放源码的一个奇迹,亦是开放源码得以延续和发展的推动者,是版本控制的经典。CVS 是常用的版本控制工具。

Starteam 是一个集合了版本控制和缺陷控制两种功能的软件,并且具有 CVS 没有的强大的图形界面,易学易用。2002年底被Borland公司收购,发展前景未知,它是我是用的第一个大型商用版本控制软件(真的付了Money的呦)。


评价 CVS、STARTEAM 孰优孰劣,是一个仁者见仁,智者见智的问题。

Starteam 的图形化界面,能够使初学者易于接收,而且其缺陷控制功能的功能(基于数据库的Change Request),是CVS 不具有的,更是相应工具中独树一帜的。

CVS的优秀跨平台能力、强大的命令行、清晰的服务器端数据结构更便于数据的备份、灾难恢复和可靠性。Simple is Butiful 送给 CVS 一定没错。

侧重不同

CVS专注于配置管理软件范畴中的版本管理系统。而配置管理系统除了包括版本管理外,还包括构建管理(Build Management)和缺陷跟踪系统。而Starteam包括了这三项。本文档也就只比较其版本管理系统的异同。

权限控制

一般来说,CVS的权限设置单一,通常只能通过CVSROOT/passwd, CVSROOT/readers, CVSROOT/writers 文件,同时还要设置CVS REPOS的物理目录权限来完成权限设置,无法完成复杂的权限控制;而STARTEAM无需通过物理路径的权限设置,而是通过自己的数据库管理,实现了类似WINDOWS NT的域用户管理和目录文件ACL控制。

但是CVS通过CVSROOT目录下的脚本,提供了相应功能扩充的接口,不但可以完成精细的权限控制,还能完成更加个性化的功能。

易用性

Starteam的图形界面功能强大,但其命令行功能较CVS弱,需要自己编写shell脚本加强。而随着WINCVS作为图形客户端的可用性的增强,Starteam的强项正在被削弱。

Label的管理

CVS 的 label 建立在文件上,难以确定到底有多少存在的 label ,而STARTEAM(图形界面)可以很方便知道有哪些 View Label及Revision Label。

CVS的版本分支, label是建立在文件上,工作在其他分支的程序同样会看到其它分支的label;而Starteam的label只在同一个视图内有效,有独立的命名空间。

STARTEAM具有Promotion states,可以看作是label的标签。在label上又封装一层的 Promotion State 便于记录版本的提升,和建立自动编译;而CVS 没有浮动 label 的概念,只能通过文件记录方式实现(如我们使用 .promotion 文件记录当前稳定的 label)。

文件缓存

Starteam 存在CACHE目录,缓存了所有 Checkout的版本的文件,因此 Checkout速度快。而CVS没有缓存,check out过程较慢,尤其是分支的 Checkout。


但我对此表示怀疑。尤其是Starteam Unix客户端基于JAVA技术,速度明显比CVS要慢。


操作文件名和目录名

CVS的REPOSITORY的物理存储结构即为项目的组织结构,使得文件名修改和目录的重新组织成为难题,往往需要管理员权限去手动操作Repository;而STARTEAM的Repository的文件结构和视图的文件结构可以完全不同,目录、文件名修改和移动非常方便,基于数据库的文件名管理还可以方便地在不同工程之间共享文件,协同工作。

CVS是程序员的工具,STARTEAM还是管理项目的工具

个人文件管理或小项目的组织,需要轻量级的管理,和灵活的文件导入、导出,以及和自由代码的交互,则CVS,Perforce,PVCS,SourceSafe等面向文件的版本控制占优势。对于公司、大项目,需要独立的测试、QA等分工,还要更多的考虑多样的用户权限控制,易用性(图形界面),缺陷控制,则需要面向工程的STARTEAM来进行版本控制和开发。

CVS的优势

CVS的优势:项目文件可以方便的组合和移植,这是因为CVS以文件为核心,即面向文件的管理方式。而且目前网络上很多开放源码都采用CVS,可以很好沟通。

CVS配置简单、健壮、可以很容易地移植;STARTEAM集成度较高,移植过程复杂,需要的管理负担大,需要完善的备份计划。

CVS是开发源码,服务器端存储易于理解,便于控制;而Starteam为商业软件,服务器端存储方式封闭,难以管理。但是 CVS 不提供图形界面,有较长的学习曲线。

Starteam 的劣势

不支持分支的合并,需要过多的手动干预。而CVS可以自动完成。

速度慢,一定程度上影响开发效率。

不支持并行开发,不能很好解决Merge的问题。而CVS可以智能 Merge。

故障恢复困难,需要有专职管理员维护。而CVS易于维护。

评价优劣,不如先用先得

不用刻意去取舍哪一个,只要用好,即可。况且,已经有了完美的CVS、STARTEAM互相转换的方法。(参见:《CVS, Starteam互相转换》)

转载自:
http://se.csai.cn/casepanel/CM/No101.htm

2010年6月29日星期二

使用pyExcelerator创建自定义分页的Excel文件

项目中要用Python创建自定义报表,其中要求每个事务占excel的一页,需要抛弃默认的分页选项,自定义分页。

excel分页其实就是在excel文件中的适当位置插入page breaks(分页符)。pyExcelerator 中有相关的借口允许用户调用并自定义分页符位置。

分页符记录在biff8中的记录块分别是HorizontalPageBreaksRecord和VerticalPageBreaksRecord:

class HorizontalPageBreaksRecord(BiffRecord):
"""
This record is part of the Page Settings Block. It contains all
horizontal manual page breaks.

Record HORIZONTALPAGEBREAKS, BIFF8:
Offset Size Contents
0 2 Number of following row index structures (nm)
2 6nm List of nm row index structures. Each row index
structure contains:
Offset Size Contents
0 2 Index to first row below the page break
2 2 Index to first column of this page break
4 2 Index to last column of this page break

The row indexes in the lists must be ordered ascending.
If in BIFF8 a row contains several page breaks, they must be ordered
ascending by start column index.
"""

class VerticalPageBreaksRecord(BiffRecord):
"""
This record is part of the Page Settings Block. It contains all
vertical manual page breaks.

Record VERTICALPAGEBREAKS, BIFF8:
Offset Size Contents
0 2 Number of following column index structures (nm)
2 6nm List of nm column index structures. Each column index
structure contains:
Offset Size Contents
0 2 Index to first column following the page
break
2 2 Index to first row of this page break
4 2 Index to last row of this page break

The column indexes in the lists must be ordered ascending.
If in BIFF8 a column contains several page breaks, they must be ordered
ascending by start row index.
"""

具体的接口就是在worksheet中set_vert_page_breaks和set_horz_page_breaks。先上程序:


from pyExcelerator import *

wb = Workbook()
ws = wb.add_sheet('0')
horz_page_breaks_list=[]

for i in range (200):
for j in range (20):
ws.write(i,j,'BIG')
else:
for i in range(39):
#5 rows each page
horz_page_breaks_list.append([(i+1)*5,0,0])

ws.set_horz_page_breaks(horz_page_breaks_list)

wb.save('page_breaks.xls')
print 'successful set page breaks!'


这个是设置5行一页,每页列数按照默认值。

2010年6月28日星期一

Python 绝对简明手册

1. 阅读须知

文中使用

>>>
作为会命令行中的输出信息的前缀

对于不清楚用用途的函数可以在解释器下面输入

help(函数名)
来获取相关信息

另外,自带的文档和google也是不可少的

2. 基本语法

2.1. if / elif / else


x=int(raw_input("Please enter an integer:"))#获取行输入

if x>0:
print '正数'
elif x==0:
print '零'
else:
print '负数'
此外C语言中类似"xxx?xxx:xxx"在Python中可以这样写

>>>number=8
>>>print "good" if 8==number else "bad" #当满足if条件时返回"good",否则返回"bad"
good
2.2. in

in判断 一个数 是否在 一个集合(如:元组,列表等) 中


if 'yes' in ('y','ye','yes'):print 'ok'
2.3. for ... in

python中没有类似C中的for循环,而是使用for...in来对集合中的每一个元素进行操作

a=['cat','door','example']
for x in a:
print x
如果要修改a的内容,请用a的副本循环(否则不安全),如:

a=["cat","zsp007@gmail.com"]
for x in a[:]:
if len(x)>6:a.insert(0,x)
>>>a
['zsp007@gmail.com', 'cat', 'zsp007@gmail.com']
若需要得到循环的次数,参见 函数 range 的用法

2.4. break / continue

这两个的用法和C中相同

for i in range(10):
if 2==i:continue #结束当前循环,进入下一步循环
if 6==i:break #跳出循环
print i
输出

0
1
3
4
5
2.5. while / pass


while True:
pass #什么也不做
2.6. is

用来比较两个变量是否指向同一内存地址(也就是两个变量是否等价) 而 == 是用来比较两个变量是否逻辑相等

a=[1,2]
b=[1,2]
>>> a is b
False
>>> a == b
True
2.7. del

用于删除元素

a=[1,2,3,4,5,6]

del a[0]
a
>>>[2,3,4,5,6]

del a[2:4]
a
>>>[2,3,6]

del a[:]
a
>>>[]

del a
a
#抛出异常
>>>NameError: name 'a' is not defined
2.8. try ... except ... finally / raise

try ... except用于异常处理

try:
x=int(raw_input("请输入数字:"))
except ValueError: #可以同时捕获多个异常,写法如except(RuntimeError,ValueError):
#当输入非数字时
print"您输入不是数字"
except: #省略异常名,可以匹配所有异常,慎用
pass
else:#当没有异常时
print 'result=',result
finally:#和Java中类似。一般用于释放资源,如文件,网络连接。
print 'finish'
raise用于抛出异常,可以为自定义的异常类

惯例是以Error结尾的类,同类的异常一般派生自同一个基类(如Exception)

class MyError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
return reper(self.value)
基类异常可以匹配派生类异常


try:
raise Exception("spam","egg")
except Exception,inst:#inst为该异常类的实例,为可选项
print type(inst) #异常的类型
print inst
3. 内建类型

3.1. None

None 表示该值不存在,比如 没有定义返回值 的函数就 返回None

3.2. Ture / False

布尔类型,Ture等价于1,False等价于0

3.3. List


>>>test=[1,2,"yes"]
3.3.1. 内建函数

append(x) 追加到链尾

extend(L) 追加一个列表,等价于+=

insert(i,x) 在位置i插入x

remove(x) 删除第一个值为x的元素,如果不存在会抛出异常

reverse() 反转序列

pop([i]) 返回并删除位置为i的元素,i默认为最后一个元素(i两边的[]表示i为可选的,实际不用输入)

index(x) 返回第一个值为x的元素,不存在则抛出异常

count(x) 返回x出现的次数

sort() 排序

例子:

>>>test=[1,2,"yes"]

>>>test.append(1) #追加到链尾
>>>test
[1, 2, 'yes', 1]

>>>test.extend([ 'no','maybe']) #追加一个列表
>>>test
[1, 2, 'yes', 1, 'no', 'maybe']

>>> test.insert(0,'never') #在位置0插入'never'
>>> test
['never', 1, 2, 'yes', 1, 'no', 'maybe']

>>> test.remove('no') #删除第一个值为"no"的元素,如果不存在会抛出异常
>>> test
['never', 1, 2, 'yes', 1, 'maybe']

>>> test.reverse() #反转序列
>>> test
['maybe', 1, 'yes', 2, 1, 'never']

>>> test.pop() #返回并删除位置为i的元素,i默认为最后一个元素
'never'
>>> test
['maybe', 1, 'yes', 2, 1]

>>> test.index('yes') #返回第一个值为'yes'的元素,不存在则抛出异常
2

>>> test.count(1) #返回1出现的次数
2

>>>test.sort() #排序
>>> test
[1, 1, 2, 'maybe', 'yes']
3.3.2. 切片

从序列中抽取一部分

>>> test=['never', 1, 2, 'yes', 1, 'no', 'maybe']

>>> test[0:3] #包括test[0],不包括test[3]
['never', 1, 2]

>>> test[0:6:2] #包括test[0],不包括test[6],而且步长为2
['never', 2, 1]

>>> test[:-1] #包括开始,不包括最后一个
['never', 1, 2, 'yes', 1, 'no']

>>> test[-3:] #抽取最后3个
[1, 'no', 'maybe']

>>>test[::-1] #倒序排列
['maybe', 'no', 1, 'yes', 2, 1, 'never']
3.3.3. 列表推导式

可以直接通过for循环生成一个list


>>>freshfruit=[' banana ',' loganberry ']
>>>[weapon.strip() for weapon in freshfruit]
['banana', 'loganberry']
说明:strip()是去除字符串两端多于空格,该句是去除序列中的所有字串两端多余的空格


>>>vec=[2,4,6]
>>>[3*x for x in vec if x>3]
[12, 18]

>>>[(x,x**2) for x in vec]
#循环变量要是一个sequence,而[x,x**2 for x in vec]是错误的
[(2,4),(4,16),(6,36)]

>>>vec2=[4,3,-9]

>>>[x*y for x in vec for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]

>>>[vec[i]+vec2[i] for i in range(len(vec))]
[6, 7, -3]

>>>[str(round(355/113.0,i)) for i in range(1,6)]
#str()是转换类型为可以打印的字符
#round(x,n)表示对x保留n位小数(四舍五入)
['3.1', '3.14', '3.142', '3.1416', '3.14159']
3.4. 元组

一旦初始化便不能更改的数据结构,速度比list快


>>>t=1234,5567,'hello' #t=(1234,5567,'hello')的简写

>>>x,y,z=t #拆分操作可以应用于所有sequence
>>>x
1234

>>>u=t,(1,2,3)
>>>u
((1234,5567,'hello'),(1,2,3))

>>>empty=() #空元组
>>>singleton='hi', #单个元素的元组,注意逗号
通过元组可以很简单的进行数据交换. 比如:

a=1
b=2
a,b=b,a
3.5. set

set(集合):无序不重复的元素集


>>>basket = ['apple','orange','apple','pear','apple','banana']

>>>fruit=set(basket)

>>>fruit
set(['orange', 'pear', 'apple', 'banana'])

>>>'orange' in fruit
True

>>>a=set('abracadabew')
>>>a
set(['a', 'c', 'b', 'e', 'd', 'r', 'w'])

>>>b=set('wajgwaoihwb')
>>>b
set(['a', 'b', 'g', 'i', 'h', 'j', 'o', 'w'])

>>>a-b #差
set(['c', 'r', 'e', 'd'])

>>>a|b #并
set(['a', 'c', 'b', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r', 'w'])

>>>a&b #交
set(['a', 'b', 'w'])

>>>a^b #(并-交)
set(['c', 'e', 'd', 'g', 'i', 'h', 'j', 'o', 'r'])
3.6. dict

字典:关键字为不可变类型,如字符串,整数,只包含不可变对象的元组.

列表等不可以作为关键字.

如果列表中存在关键字对,可以用dict()直接构造字典.而这样的列表对通常是由列表推导式生成的.


>>>tel={'jack':4098,'sape':4139}

>>>tel['guido']=4127

>>>tel
{'sape': 4139, 'jack': 4098, 'guido': 4127}

>>>tel['jack'] #如果jack不存在,会抛出KeyError
4098
>>>a.get("zsp",5000) #如果"zsp"为tel的键则返回其值,否则返回5000

>>>del tel['sape'] #删除键'sape'和其对应的值
>>>tel.keys() #复制一份键的副本,同理tel.items()为值的副本
['jack', 'guido']

>>>"jack" in tel #判断"jack"是否tel的键
True
>>>"zsp" not in tel
True

>>>for k,v in tel.iteritems():print k,v #同理tel.iterkeys()为键的迭代器,tel.itervalues()为值的迭代器
jack 4098
guido 4127

>>>tel.copy() #复制一份tel
{'jack': 4098, 'guido': 4127}

>>> tel.fromkeys([1,2],0) #从序列生成并返回一个字典,其值为第二个参数(默认为None),不改变当前字典
{1: 0, 2: 0}

>>>tel.popitem() #弹出一项
('jack', 4098)
4. 函数相关

4.1. 函数定义 / 参数默认值


def fib(n=2,a=1):#参数可以有默认值
"""这里给函数写文档注释"""
for i in range(n):
print a


>>>f=fib #可以用一个变量表示函数
>>>f(3)
1
1
1

>>>fib(a=2) #多个可选参数赋值可以直接写"参数变量名=值"来快速赋值
2
2
4.2. Lambda函数

一种无名函数的速写法

def make_incrementor(n):
return lambda x: x+n

f=make_incrementor(n)
#f等价于
#def f(x):
# return x+n
4.3. 不定长参数 *para,**para

参数格式为 *para 表示接受一个元组

为 **para 表示接受一个字典

*para要在**para之前


def test(*args,**dic):
for arg in args :
print arg
for k,v in dic.iteritems():
print k ,':',v

>>> test("yes",1,2,me="张沈鹏",where="中国") #"yes",1,2传递给元组;me="张沈鹏",where="中国"传递给字典
yes
1
2
me : 张沈鹏
where : 中国
4.4. @ 装饰器

@A def B:pass 等价于 def B:pass B=A(B) 即将函数B作为参数传给参数A

from time import time
#测试运行时间
def cost_time(func):
def result(*args,**dic):
beign=time()
func(*args,**dic)
print "cost time : ",time()-beign
return result

@cost_time
def show(n):
for x in range(n):print x

>>> show(10)
0
1
2
3
4
5
6
7
8
9
cost time : 0.0469999313354
4.5. 生成器表达式

生成器表达式:类似于没有中括号的列表推导式,可用在参数中

>>>sum(i*i for i in range(10))
285

>>>unique_words=set(word for line in page for word in line.split())#page为打开的文件

>>>data='golf'

>>>list(data[i] for i in range(len (data)-1,-1,-1))
['f','l','o','g']
4.6. yield

每次调用返回一个值,并记录当前执行位置所有的变量

def reverse(data):
for index in range(len(data)-1,-1,-1):
yield data[index]

for char in reverse("golf"):
print char,
输出

f l o g
5. 常用函数

5.1. eval

对字符串参数运算,求值

>>> eval("1 + 2*3") #可以方便的用来做四则运算
7
>>> a=1
>>> eval('a+1') #可以访问变量
2
5.2. exec

将字符串参数作为python脚本执行

>>> exec('a="Zsp"')
>>> a
'Zsp'
5.3. execfile

和exec类似,不过是用来打开一个文件,并作为python脚本执行

5.4. dir

显示对象的所有属性(即可以用"."操作直接访问)

>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
5.5. help

help(类/函数) 返回相应对象的文档字符串

>>> help(vars)
Help on built-in function vars in module __builtin__:

vars(...)
vars([object]) -> dictionary

Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
5.6. len

返回序列/字典的长度

>>> len([1,2,3])
3
5.7. print

输出字符串 用法演示:

print "Today ", #加逗号,输出后不换行

name="ZSP"

print name,"cost $",10 #输出多个变量

print "hello,%s!"%name #%s 表示用str转化为字符串

for x in xrange(1,11):
print '%2d %3d' % (x,x*x) #小数输出如 %5.3f
对于字典可以用变量名来直接格式化,如:

>>>table={'Sjoerd':4127,'Jack':4098,'Dcab':8637678}
>>>print 'Jack:%(Jack)d; Sjoerd:%(Sjoerd)d; Dcab:%(Dcab)d' %
table
Jack:4098; Sjoerd:4127; Dcab:8637678
同时,函数vars()返回包含所有变量的字典,配合使用,无坚不摧!

5.8. raw_input


x=raw_input("Please enter an sentence:") #将输入的内容赋值给x
5.9. range


range(10,0,-3)#参数的含义为起点(默认为0),终点(不含终点),步长(默认为1)
>>>[10,7,4,1]
和for...in配合使用

a=['cat','door','example']
for i in range(len(a)):#len()函数为求序列的长度
print i,a[i]
5.10. filter

filter(function , sequence) 返回序列,为原序列中能使function返回true的值

>>>a=[1,2,3,4]
>>>filter(lambda x:x%2,a)
[1, 3]
5.11. map

map(function,sequence,[sequence...])

返回序列,为对原序列每个元素分别调用function获得的值.

可以传入多个序列,但function也要有相应多的参数,如

map(lambda x,y,z:x+y+z,range(1,3),range(3,5),range(5,7))

计算过程为

1+3+5=9

2+4+6=12

返回[9,12]

5.12. reduce

reduce(function,sequence,[init])

返回一个单值为,计算步骤为 :

第1个结果=function(sequence[0],sequence[1])
第2个结果=function(第1个结果,sequence[2])
返回最后一个计算得值
如果有init,则先调用function(init,sequence[0])
sequence只有一个元素时,返回该元素,为空时抛出异常.
如 reduce(lambda x,y:x+y,range(3),99) 的计算为

99+0=99 => 99+1=100 => 100+2=102

返回102

注:实际使用中用内建函数sum来完成这个累加更合适,如这里等价sum(range(3),99)

5.13. zip

zip用于多个sequence的循环

questions=['name','quest','favorite color']
answers=['lancelot','the holy grail','blue']

for q,a in zip(questions,answers):
print 'What is your %s ? It is %s.'%(q,a)
输出:

What is your name ? It is lancelot.
What is your quest ? It is the holy grail.
What is your favorite color ? It is blue.
5.14. reversed反向循环


for i in reversed(range(1,4)):
print i
输出:

3
2
1
5.15. sorted排序

返回一个有序的新序列

>>>sorted([2,5,1,4])
[1, 2, 4, 5]
5.16. enumerate 返回索引位置和对应的值


for i,v in enumerate(['tic','tac','toe'])
print i,v
输出:

0 tic
1 tac
2 toe
5.17. open/文件操作

f=open('/tmp/hello','w')

#open(路径+文件名,读写模式)

#读写模式:r只读,r+读写,w新建(会覆盖原有文件),a追加,b二进制文件.常用模式

如:'rb','wb','r+b'等等

f.read([size]) size未指定则返回整个文件,如果文件大小>2倍内存则有问题.f.read()读到文件尾时返回""(空字串)

file.readline() 返回一行

file.readline([size]) 返回包含size行的列表,size 未指定则返回全部行

for line in f: print line #通过迭代器访问

f.write("hello\n") #如果要写入字符串以外的数据,先将他转换为字符串.

f.tell() 返回一个整数,表示当前文件指针的位置(就是到文件头的比特数).

f.seek(偏移量,[起始位置])

用来移动文件指针

偏移量:单位:比特,可正可负

起始位置:0-文件头,默认值;1-当前位置;2-文件尾

f.close() 关闭文件

6. 模块化

6.1. 导入模块

模块的查找路径

1.当前的目录

2.环境变量PYTHONPATH所指的目录列表

3.python解释器的安装目录

如将代码保存上述的一个目录中的的fibo.py文件中,便可以


import fibo
fibo.function()
如果想直接使用fibo.function可以重命名这个函数,如


f=fibo.function
f()
也可以


form fibo import function
function()
甚至可以form fibo import *

可以 form 包.子包.模块 imort 函数

然后就直接使用该函数,不需要加前缀

6.2. 包

引用推荐写法为

form 包 import 模块

几个功能类似的模块可以组合成一个包,

比如一个可以处理.wav,.mp3,.wma等音频文件的有类似如下结构:


Sound/
__init__.py
Formats/
__init__.py
wavread.py
wavwrite.py
mp3read.py
mp3write.py
wmaread.py
wmawrite.py
Effects/
__init__.py
echo.py
surround.py
reverse.py
只有当init.py存在时python才将该文件夹视为一个包.

该文件可以为空文件 一般在init.py文件中定义一个all列表,包含要import *时要导入的模块. 如Sound/Effects/init.py可以有如下内容

__all__=["echo","surround","reverse"]

包的作者在发布包时可以更新这个列表,也可以根据需要让某个模块不支持import *

对于包中同一个文件夹下的模块可以把

form 包.子包 imort 模块

简写为 imort 模块

6.3. 面向对象

6.3.1. 概要


class ClassName:
"类文档,可以通过类名.__doc__访问"
def f(self):#self为每个类函数的必要的一个参数,可以通过它来访问当前实例
return self.content

def __init__(self,word=''):#构造函数
#构造函数,可以初始化变量,可以有参数"
self.content=word
self.__name=word #私有变量,以"__"开头,不以"__"结尾的变量
创建类实例 x=ClassName("good")

6.3.2. 类继承

class DerivedClassName(BassClassName):

pass
如果基类定义在另一个模块中, 要写成

modname.BaseClassName

派生类的函数会覆盖基类的同名函数

如果想扩充而不是改写基类的函数,可以这样调用基类函数

BaseClassName.methodname(self,arguments)

注意:该基类要在当前全局域或被导入

class A:
def hi(self):
print "A"
class B:
def hi(self):
A.hi(self)
super(B).hi() #通过super关键字可以获得当前类的基类
print "B"

B().hi()
输出

A
B
6.3.3. 多重继承

类多继承

class DerivedClassName(Base1,Base2,Base3):
pass
对于该类函数的解析规则是深度优先,先是Base1,然后是Base1的基类,诸如此类.

class A:
def hi(self):
print "A"

class B:
def hi(self):
print "B"

class C(A,B):
pass

C().hi()
输出:

A
6.4. 操作符重载

通过定义类的一些约定的以""开头并结尾的函数,可以到达重载一些特定操作的目的,下面是是一些常用的重载

6.4.1. __str__ / __unicode__

当print一个对象实例时,实际是print该实例str()函数的返回值.

class A:
def __str__(self):
return "A"
def __unicode__(self):
return "uA"

print A()
print unicode(A())
输出

A
uA
unicode和str类似,不过返回Unicode字符串.

6.4.2. 比较操作

x
x<=y x.le(y)

x==y x.eq(y)

x!=y 或 x<>y x.ne(y)

x>y x.gt(y)

x>=y x.ge(y)

cmp( self, other) 用来简化比较函数的定义 self < other返回负数,相等时返回0,self>other时返回正数


class A:
def __init__(self,i):
self.i=i
def __cmp__(self,other):
return self.i-other.i

print A(1)>A(2)
输出

False
6.4.3. __iter__

for ... in 循环即就是通过这个函数遍历当前容器的对象实例 可配合yield方便的编写这个函数(参见基本语法yield)

class A:
def __init__(self,n):
self.n=n
def __iter__(self):
n=self.n
while n:
m=n%2
n/=2
yield m

for i in A(5):
print i,
输出

1 0 1
另有一种繁琐的实现: 返回一个可以通过next()函数遍历的对象,当结束时抛出StopIteration异常

6.5. 类相关函数

6.5.1. type

返回对象的类型

>>> type("")

>>> type("")==str
True

>>> type([])

>>> type([])==list
True

>>> type({})


>>> type(())


>>> class A:pass

>>> type(A)


>>> type(A())


>>> import types #在types模块中有许多类型的定义

>>> type(A)==types.ClassType
True
6.5.2. getattr / hasattr /delattr

getattr:通过类实例和一个字符串动态的调用类函数/属性

class A:
def name(self):
return "ZSP"
def hello(self):
return "nice to meet me ."

def say(obj,attr):
print getattr(obj,attr)()

a=A()
say(a,"name")
say(a,"hello")
输出

ZSP
nice to meet me .
hasattr 用来判断实例有无该函数/属性

delattr 用来删除实例的函数/属性

6.5.3. property

通过值的方式调用实例无参函数

class A(object):
def __init__(self): self._x = None
def getx(self): return self._x
def setx(self, value): self._x = value
def delx(self): self._x=None
x = property(getx, setx, delx, "I'm the 'x' property.")
a=A()
print a.x

a.x="ZSP"
print a.x

del a.x
print a.x
输出

None
ZSP
None
可以方便的定义一个只读属性

class A(object):
@property
def x(self): return "Property"
调用

>>>a=A()

>>>print a.x
Property

>>>a.x="ZSP" #只读属性,不能更改
Traceback (most recent call last):
File "D:\Profile\Untitled 2.py", line 9, in
a.x="ZSP"
AttributeError: can't set attribute
6.5.4. isinstance( object, classinfo)

判断一个对象是否是一个类的实例

>>>class A:pass

>>>class B:pass

>>>a=A()

>>>isinstance(a,A)
True

>>>isinstance(a,B)
False
Python 常用模块体验 ::-- ZoomQuiet [2007-11-10 06:37:48]

目录
Py常用模块汇编
zshelve 对象持久模块
发布
补丁::
fast UserDict
CPUG联盟::
CPUG::门户plone
BPUG
SPUG
ZPUG
SpreadPython Python宣传
7. Py常用模块汇编

'Python 标准库2.0 整理者

Python 江湖 QQ 群: 43680167
Feather (校对) gt: andelf@gmail.com
一些有用的Python函式庫列表 » 程式設計 遇上 小提琴

::-- ZoomQuiet [2007-11-10 07:39:01]


CPUG联盟::
CPUG::门户plone
BPUG
SPUG
ZPUG
SpreadPython Python宣传
7.1. zshelve 对象持久模块

{{{Jiahua Huang reply-to python-cn@googlegroups.com, to "python. cn" , date Nov 8, 2007 5:41 PM subject [CPyUG:34726] 贴个 zlib 压缩的 zshelve 对象持久模块 }}} 这个给 Python 标准库的 shelve.py 添加了 zlib 压缩, 减小数据库文件体积,以改善磁盘 io 性能

7.1.1. 发布

http://zshelve.googlecode.com/svn/trunk/

加了个命令行工具:

huahua@huahua:tmp$ zshelve
commandline tool for zshelve databases

Usage: zshelve FILE dump Dump the data tree
zshelve FILE keys List of keys
zshelve FILE get KEY Dump value for key
zshelve FILE set KEY VALUE Set db[key] = value
zshelve FILE has_key KEY True if database has the key
zshelve FILE search_key KEY Search key
zshelve FILE search_value VALUE Search value

huahua@huahua:tmp$ zshelve set tes.db a 1
huahua@huahua:tmp$ zshelve dump tes.db
|- a
| | - 1
huahua@huahua:tmp$ zshelve set tes.db b "dict(a=1,b=2,c=3,d={'s':'4'})"
huahua@huahua:tmp$ zshelve dump tes.db
|- a
| |- 1
|- b
| |- a
| | |- 1
| |- c
| | |- 3
| |- b
| | |- 2
| |- d
| | |- s
| | | |- 4
对比::

>>> import zshelve
>>> import shelve
>>> zdb = zshelve.open('/tmp/zshelve.db')
>>> db = shelve.open('/tmp/shelve.db')
>>> zdb['1'] = dict(a='0123456789'*10000000)
>>> db['1'] = dict(a='0123456789'*10000000)
>>> zdb.sync()
>>> db.sync()
看看文件大小差异::

huahua@huahua:zshelve$ ll /tmp/*shelve.db
-rw-r--r-- 1 huahua huahua 96M 2007-11-08 17:36 /tmp/shelve.db
-rw-r--r-- 1 huahua huahua 204K 2007-11-08 17:36 /tmp/zshelve.db
7.1.2. 补丁::


--- shelve.py 2007-05-03 00:56:36.000000000 +0800
+++ zshelve.py 2007-11-08 17:25:59.000000000 +0800
@@ -70,6 +70,7 @@ except ImportError:

import UserDict
import warnings
+import zlib ## use zlib to compress dbfile

__all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]

@@ -80,13 +81,14 @@ class Shelf(UserDict.DictMixin):
See the module's __doc__ string for an overview of the interface.
"""

- def __init__(self, dict, protocol=None, writeback=False):
+ def __init__(self, dict, protocol=None, writeback=False, compresslevel=2):
self.dict = dict
if protocol is None:
protocol = 0
self._protocol = protocol
self.writeback = writeback
self.cache = {}
+ self.compresslevel = compresslevel

def keys(self):
return self.dict.keys()
@@ -109,7 +111,7 @@ class Shelf(UserDict.DictMixin):
try:
value = self.cache[key]
except KeyError:
- f = StringIO(self.dict[key])
+ f = StringIO(zlib.decompress(self.dict[key]))
value = Unpickler(f).load()
if self.writeback:
self.cache[key] = value
@@ -121,7 +123,7 @@ class Shelf(UserDict.DictMixin):
f = StringIO()
p = Pickler(f, self._protocol)
p.dump(value)
- self.dict[key] = f.getvalue()
+ self.dict[key] = zlib.compress(f.getvalue(), self.compresslevel)

def __delitem__(self, key):
del self.dict[key]
@@ -168,32 +170,32 @@ class BsdDbShelf(Shelf):
See the module's __doc__ string for an overview of the interface.
"""

- def __init__(self, dict, protocol=None, writeback=False):
- Shelf.__init__(self, dict, protocol, writeback)
+ def __init__(self, dict, protocol=None, writeback=False, compresslevel=2):
+ Shelf.__init__(self, dict, protocol, writeback, compresslevel)

def set_location(self, key):
(key, value) = self.dict.set_location(key)
- f = StringIO(value)
+ f = StringIO(zlib.decompress(value))
return (key, Unpickler(f).load())

def next(self):
(key, value) = self.dict.next()
- f = StringIO(value)
+ f = StringIO(zlib.decompress(value))
return (key, Unpickler(f).load())

def previous(self):
(key, value) = self.dict.previous()
- f = StringIO(value)
+ f = StringIO(zlib.decompress(value))
return (key, Unpickler(f).load())

def first(self):
(key, value) = self.dict.first()
- f = StringIO(value)
+ f = StringIO(zlib.decompress(value))
return (key, Unpickler(f).load())

def last(self):
(key, value) = self.dict.last()
- f = StringIO(value)
+ f = StringIO(zlib.decompress(value))
return (key, Unpickler(f).load())


@@ -204,12 +206,12 @@ class DbfilenameShelf(Shelf):
See the module's __doc__ string for an overview of the interface.
"""

- def __init__(self, filename, flag='c', protocol=None, writeback=False):
+ def __init__(self, filename, flag='c', protocol=None,
writeback=False, compresslevel=2):
import anydbm
- Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback)
+ Shelf.__init__(self, anydbm.open(filename, flag), protocol,
writeback, compresslevel)


-def open(filename, flag='c', protocol=None, writeback=False):
+def open(filename, flag='c', protocol=None, writeback=False, compresslevel=2):
"""Open a persistent dictionary for reading and writing.

The filename parameter is the base filename for the underlying
@@ -222,4 +224,4 @@ def open(filename, flag='c', protocol=No
See the module's __doc__ string for an overview of the interface.
"""

- return DbfilenameShelf(filename, flag, protocol, writeback)
+ return DbfilenameShelf(filename, flag, protocol, writeback, compresslevel)

一行代码让 UserDict.UserDict 的类加速 4 倍
::-- ZoomQuiet [2007-11-10 07:34:49]

目录
fast UserDict

7.2. fast UserDict

{{{Jiahua Huang reply-to python-cn@googlegroups.com, to "python. cn" , date Nov 10, 2007 3:28 PM subject [CPyUG:34791] 一行代码让 UserDict.UserDict 的类加速 4 倍 }}} 发现 Python 标准库里好些字典类从 UserDict.UserDict 派生, 而不是从 dict 派生, 是因为 旧版 python 内建类型不能派生子类,

那么这会不会影响速度呢,

先给两个分别继承 UserDict.UserDict 和 dict 的类 URdict, Rdict

>>> import UserDict
>>> class URdict(UserDict.UserDict):
... '''dict can search key by value
... '''
... def indexkey4value(self, value):
... '''search key by value
... >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
... >>> rd.indexkey4value('Other')
... 'b'
... '''
... try:
... ind = self.values().index(value)
... return self.keys()[ind]
... except:
... return None
... def key4value(self, svalue):
... '''search key by value
... >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
... >>> rd.key4value('Other')
... 'b'
... '''
... for key, value in self.iteritems():
... if value == svalue:
... return key
... def keys4value(self, svalue):
... '''search keys by value
... >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
... >>> rd.keys4value('Other')
... ['b', 'e']
... '''
... keys=[]
... for key, value in self.iteritems():
... if value == svalue:
... keys.append(key)
... return keys
...
>>>
>>> class Rdict(dict):
... '''dict can search key by value
... '''
... def indexkey4value(self, value):
... '''search key by value
... >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
... >>> rd.indexkey4value('Other')
... 'b'
... '''
... try:
... ind = self.values().index(value)
... return self.keys()[ind]
... except:
... return None
... def key4value(self, svalue):
... '''search key by value
... >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
... >>> rd.key4value('Other')
... 'b'
... '''
... for key, value in self.iteritems():
... if value == svalue:
... return key
... def keys4value(self, svalue):
... '''search keys by value
... >>> rd = Rdict(a='One', b='Other', c='What', d='Why', e='Other')
... >>> rd.keys4value('Other')
... ['b', 'e']
... '''
... keys=[]
... for key, value in self.iteritems():
... if value == svalue:
... keys.append(key)
... return keys
...
>>>

>>> import time
>>> def _timeit(_src):
... exec('''
... _t0 = time.time()
... %s
... _t1 = time.time()
... _t3 = _t1 - _t0
... '''%_src)
... return _t3
...
>>> ran = range(100000)

再弄俩实例
>>> u = URdict()
>>> r = Rdict()

看看插入速度
>>> _timeit("for i in ran: u[i]=i")
0.1777961254119873
>>> _timeit("for i in ran: r[i]=i")
0.048948049545288086

看看原始 dict 的速度
>>> _timeit("for i in ran: d[i]=i")
0.041368961334228516
可以看到, UserDict.UserDict 确实严重影响速度,

python 标准库里边好多 UserDict 的都应该换成 dict , 以提高性能

不过,一个个修改 Python 标准库似乎又不合适,

再次使用一招鲜,直接干掉 UserDict

在使用/导入那些模块前先来一行

>>> import UserDict; UserDict.UserDict = dict
完了再导入模块来试试

>>> u = URdict()
>>> _timeit("for i in ran: u[i]=i")
0.042366981506347656
一行代码让速度提高 4 倍.

转载自:
http://wiki.woodpecker.org.cn/moin/PyAbsolutelyZipManual