??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲一区无码精品色,日韩成人精品日本亚洲,亚洲乱码av中文一区二区http://m.tkk7.com/renyangok/category/20450.htmlzh-cnFri, 21 Dec 2007 16:03:29 GMTFri, 21 Dec 2007 16:03:29 GMT60转:谈base64~码http://m.tkk7.com/renyangok/archive/2007/11/19/161606.html保尔?/dc:creator>保尔?/author>Mon, 19 Nov 2007 06:30:00 GMThttp://m.tkk7.com/renyangok/archive/2007/11/19/161606.htmlhttp://m.tkk7.com/renyangok/comments/161606.htmlhttp://m.tkk7.com/renyangok/archive/2007/11/19/161606.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/161606.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/161606.html
打开一EmailQ查看其原始信息Q您可以通过收取、导邮g用文本编辑器查看Q。你会看到类DL一个效果:

Date: Thu, 25 Dec 2003 06:33:07 +0800
From: "eSX?!" <snaix@yeah.net'>snaix@yeah.net'>snaix@yeah.net'>snaix@yeah.net>
Reply-To: snaix@yeah.net'>snaix@yeah.net'>snaix@yeah.net'>snaix@yeah.net
To: "snaix" <snaix@126.com'>snaix@126.com>
Subject:
X-mailer: Foxmail 5.0 beta2 [cn]
Mime-Version: 1.0
Content-Type: text/plain;
charset="gb2312"
Content-Transfer-Encoding: base64

xOO6w6OsU25haVgNCg0KoaGhodXiysfSu7j2QmFzZTY0tcSy4srU08q8/qOhDQoNCkJlc3QgV2lz
aGVzIQ0KIAkJCQkNCqGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaEgICAgICAgICAgICAgICBl
U1g/IQ0KoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoSAgICAgICAgICAgICAgIHNuYWl4QHll
YWgubmV0DQqhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhICAgICAgICAgMjAwMy0x
Mi0yNQ0K

是否看到?#8220;base64”标记Q是否看C标记下面的一行ؕ码?也许你会恍然大悟Q对Q这是Base64~码?

什么是Base64Q?/strong>

? 照RFC2045的定义,Base64被定义ؓQBase64内容传送编码被设计用来把Q意序列的8位字节描qCؓ一U不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.Q?

Z么要使用Base64Q?/strong>

在设计这个编码的时候,我想设计人员最主要考虑?个问题:
1.是否加密Q?
2.加密法复杂E度和效?
3.如何处理传输Q?

    加密是肯定的Q但是加密的目的不是让用户发送非常安全的Email。这U加密方式主要就?#8220;防君子不防小?#8221;。即辑ֈ一眼望d全看不出内容卛_?
? 于这个目的加密算法的复杂E度和效率也׃能太大和太低。和上一个理q|MIME协议{用于发送Email的协议解决的是如何收发EmailQ而ƈ? 是如何安全的收发Email。因此算法的复杂E度要小Q效率要高,否则因ؓ发送Email而大量占用资源,路就有点走歪了?

     但是Q如果是Z以上两点Q那么我们用最单的恺撒法即可,Z么Base64看v来要比恺撒法复杂呢?q是因ؓ在Email的传送过E中Q由于历史原 因,Email只被允许传送ASCII字符Q即一?位字节的?位。因此,如果您发送了一带有非ASCII字符Q即字节的最高位?Q的Email? q有“历史问题”的网x可能会出现问题。网兛_能会把最高位|ؓ0Q很明显Q问题就q样产生了!因此Qؓ了能够正常的传送EmailQ这个问题就必须 考虑Q所以,单单靠改变字母的位置的恺撒之cȝҎ也就不行了。关于这一点可以参考RFC2046?
Z以上的一些主要原因生了Base64~码?

法详解

    Base64~码要求??位字节(3*8=24Q{化ؓ4?位的字节Q?*6=24Q,之后?位的前面补两?QŞ?位一个字节的形式?
具体转化形式间下图:
字符?#8220;?”
11010101 11000101 00110011

00110101 00011100 00010100 00110011
?

可以q么考虑Q把8位的字节q成一?10101011100010100110011
然后每次序?个出来之后再把这6二进制数前面再添加两?Q就成了一个新的字节。之后再选出6个来Q再d0Q依此类推,直到24个二q制数全部被选完?
让我们来看看实际l果Q?

字符?#8220;?”
11010101 HEX:D5 11000101 HEX:C5 00110011 HEX:33

00110101 00011100 00010100 00110011
字符’5’ 字符’^"’ 字符’^T’ 字符’3’
十进?3 十进?4 十进?0 十进?1
?

q样“? ”q个字符串就被Base64表示?#8221;5^"^T3”了么Q。错Q?
Base64~码方式q不是单U利用{化完的内容进行编码。像’^"’字符是控制字W,q不能通过计算机显C出来,在某些场合就不能使用了。Base64有其自n的编码表Q?

Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v (pad) =
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y
?

q? 也是Base64名称的由来,而Base64~码的结果不是根据算法把~码变ؓ高两位是0而低6Z表数据,而是变ؓ了上表的形式Q如”A”有7位, ?#8221;a”只?位。表中,~码的编号对应的是得出的新字节的十进制倹{因此,从表2可以得到对应的Base64~码Q?

字符?#8220;?”
11010101 HEX:D5 11000101 HEX:C5 00110011 HEX:33

00110101 00011100 00010100 00110011
字符’5’ 字符’^"’ 字符’^T’ 字符’3’
十进?3 十进?4 十进?0 十进?1
字符’1’ 字符’i’ 字符’U’ 字符’z’
?

q样Q字W串“?”l过~码后就成了字符?#8220;1iUz”了?
Base64?个字节{变ؓ4个字节,因此Q编码后的代码量Q以字节为单位,下同Q约比编码前的代码量多了1/3。之所以说?#8220;U?#8221;Q是因ؓ如果代码量正好是3的整数倍,那么自然是多?/3。但如果不是呢?
l心的h可能已经注意CQ在The Base64 Alphabet中的最后一个有一?pad) =字符。这个字W的目的是用来处理q个问题的?
当代码量不是3的整数倍时Q代码量/3的余数自然就?或?。{换的时候,l果不够6位的?来补上相应的位置Q之后再?位的前面补两?。{换完I出的结果就用就?#8220;=”来补位。譬如结果若最后余下的?个字节的“?#8221;Q?

字符?#8220;?#8221;
11010101 HEX:D5 11000101 HEX:C5

00110101 00011100 00010100
十进?3 十进?4 十进?0 pad
字符’1’ 字符’i’ 字符’U’ 字符’=’
?

q样Q最后的2个字节被整理成了“1iU=”?
同理Q若原代码只剩下一个字节,那么会d两个“=”。只有这两种情况Q所以,Base64的编码最多会在编码结有两个“=”
至于Base64的解码,只是一个简单的~码的逆过E,读者可以自己探讨。我在文章的最后给码算法?

法实现
其实在算法详解的时候基本上已经说的很清楚了。用于程序上Q除ȝ束判断,大概可以分ؓ如下几步几步Q?
d数据3字节用AND取前6位,攑օ新的变量中右移两位Q高两位?AND取第一个字节的?位和W二个字节的?位移位放入新变量中右移两位Q清0……依此cL?
解码的类C语言实现的算法:
BYTE LMoveBit(int base, int MoveNum)
{
BYTE result=base;
if(MoveNum==0)return 1;
if(MoveNum==1)return MoveNum;
result=base<<(MoveNum-1);
return result;
}

char base64_alphabet[]=
{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/','='};
BYTE Base64Decode(char *base64code, DWORD base64length)
{
char buf[4];
int i,j;
int k;
int l=0;
BYTE temp1[4],temp2;
BYTE *Buffer=new BYTE[base64length*3/4];
DWORD base64a=(base64length/4)-1;
DWORD base64b=0;
for(;base64b<base64a+1;base64b++)
{
for(i=0;i<4;i++)
{
buf[i]=*(base64code+(base64b*4)+i);
for(j=0;j<65;j++)
{
if(buf[i]==base64_alphabet[j])
{
temp1[i]=j;
break;
}
}
}
i--;
for(k=1;k<4;k++)
{
if(temp1[i-(k-1)]==64){m_padnum++; continue;}
temp1[i-(k-1)]=temp1[i-(k-1)]/LMoveBit(2,(k-1)*2);
temp2=temp1[i-k];
temp2=temp2&(LMoveBit(2,k*2)-1);
temp2*=LMoveBit(2,8-(2*k));//move 4
temp1[i-(k-1)]=temp1[i-(k-1)]+temp2;
Buffer[base64b*3+(3-k)]=temp1[i-(k-1)];
}
}
return Buffer;
}

Ҏq段法Q文章最开始给出的Email内容Q可以解码ؓQ?
你好QSnaiX

q是一个Base64的测试邮Ӟ

Best Wishes!
eSX?!
snaix@yeah.net'>snaix@yeah.net'>snaix@yeah.net'>snaix@yeah.net
2003-12-25

如文章有问题恌指出q与我联p:snaix@126.com'>snaix@126.com

主要参考资料:
RFC2045
RFC2046
《奇妙的Base64~码》,|聪
以及一些来自互联网上的其他资料


]]>
pythonchallenge参考答?/title><link>http://m.tkk7.com/renyangok/archive/2007/11/02/157804.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Fri, 02 Nov 2007 09:56:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/archive/2007/11/02/157804.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/157804.html</wfw:comment><comments>http://m.tkk7.com/renyangok/archive/2007/11/02/157804.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/157804.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/157804.html</trackback:ping><description><![CDATA[-------------------------------------------------------------------------------------------------------------------------------<br /> Level 7:  http://www.pythonchallenge.com/pc/def/oxygen.html<br /> <p>The squares in the middle look suspicious so you think that the answer is encoded within it. </p> <p>Unfortunately, Python does not have a built-in Image library so you'll have to search for an external module. I've chosen to use <a class="external" title="http://www.pythonware.com/products/pil/" rel="nofollow">PIL</a><span id="qkou244" class="urlexpansion"> (<em>http://www.pythonware.com/products/pil/</em>)</span>, which I had pre-installed. </p> <pre>>>> import Image, urllib, StringIO<br /> >>> img = urllib.urlopen('http://www.pythonchallenge.com/pc/def/oxygen.png').read()<br /> >>> i = Image.open(StringIO.StringIO(img)) # Image.open requires a file-like object<br /> >>> i.size<br /> (629, 95)<br /> >>> [i.getpixel((x,45)) for x in range(629)]<br /> [(115, 115, 115, 255), (115, 115, 115, 255), (115, 115, 115, 255), ...<br /> </pre> <p>There seem to be a lot of data here, but it is noticable that the grey squares have R=G=B, and it has a period of 7 pixels. </p> <pre># Extract every 7th pixel from row 45.<br /> >>> row = [i.getpixel((x, 45)) for x in range(0, i.size[0], 7)]<br /> # Take the R value from all with equal R, G, and B values.<br /> >>> ords = [r for r, g, b, a in row if r == g == b]<br /> # And convert to characters.<br /> >>> print "".join(map(chr, ords))<br /> smart guy, you made it. the next level is [105, 110, 116, 101, 103, 114, 105, 116, 121]<br /> </pre> <p>Applying the hint: </p> <pre>>>> "".join(map(chr,[105, 110, 116, 101, 103, 114, 105, 116, 121]))<br /> 'integrity'<br /> <br /> -------------------------------------------------------------------------------------------------------------------------------<br /> <br /> Level 8: http://www.pythonchallenge.com/pc/def/integrity.html<br /> </pre> <img src ="http://m.tkk7.com/renyangok/aggbug/157804.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2007-11-02 17:56 <a href="http://m.tkk7.com/renyangok/archive/2007/11/02/157804.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ҏ和函数的区别Qmethod & functionQ?/title><link>http://m.tkk7.com/renyangok/archive/2007/11/02/157759.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Fri, 02 Nov 2007 07:26:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/archive/2007/11/02/157759.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/157759.html</wfw:comment><comments>http://m.tkk7.com/renyangok/archive/2007/11/02/157759.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/157759.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/157759.html</trackback:ping><description><![CDATA[Not a whole lot.<br /> <br /> I believe the technical difference is that a function is not in a class, whereas a method is.<br /> <br /> You'll see method and member function used interchangeably which is fine (a function that is a member of a class, get it? Correct term when discussing C++). Function and method shouldn't be used interchangeably, but often will be.<br /> <br /> I'd suggest you don't sweat it, they both represent blocks of code that do something and might return a value. <img src ="http://m.tkk7.com/renyangok/aggbug/157759.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2007-11-02 15:26 <a href="http://m.tkk7.com/renyangok/archive/2007/11/02/157759.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux~程之序列化存储Python对象http://m.tkk7.com/renyangok/archive/2007/11/02/157739.html保尔?/dc:creator>保尔?/author>Fri, 02 Nov 2007 06:10:00 GMThttp://m.tkk7.com/renyangok/archive/2007/11/02/157739.htmlhttp://m.tkk7.com/renyangok/comments/157739.htmlhttp://m.tkk7.com/renyangok/archive/2007/11/02/157739.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/157739.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/157739.html(转自Q?/strong>

上——http://www.linuxdby.com/html/linux/program/20070412/1753.html

下——http://www.linuxdby.com/html/linux/program/20070412/1754.html)

什么是持久性?

持久性的基本思想很简单。假定有一?Python E序Q它可能是一个管理日常待办事的E序Q您希望在多ơ执行这个程序之间可以保存应用程序对象(待办事项Q。换句话_您希望把对象存储在磁盘上Q便? 以后索。这是持久性。要辑ֈq个目的Q有几种ҎQ每一U方法都有其优缺炏V?

例如Q可以把对象数据存储在某U格式的文本文g中,譬如 CSV 文g。或者可以用关系数据库,譬如 Gadfly、MySQL、PostgreSQL 或?DB2。这些文件格式和数据库都非常优秀Q对于所有这些存储机ӞPython 都有健壮的接口?

q些存储机制都有一个共同点Q存储的数据是独立于对这些数据进行操作的对象和程序? q样做的好处是,数据可以作ؓ׃n的资源,供其它应用程序用。缺ҎQ用q种方式Q可以允许其它程序访问对象的数据Q这q背了面向对象的装性原? ?卛_象的数据只能通过q个对象自n的公共(publicQ接口来讉K?

另外Q对于某些应用程序,关系数据库方法可能不是很理想。尤其是Q关pL据库不理 解对象。相反,关系数据库会使用自己的类型系l和关系数据模型Q表Q,每张表包含一l元l(行)Q每行包含具有固定数目的静态类型字D(列)。如果应 用程序的对象模型不能够方便地转换到关pL型,那么在把对象映射到元l以及把元组映射回对象方面,会碰C定难度。这U困隑ָ被称为阻性不匚w Qimpedence-mismatchQ问题?

对象持久?/strong>

如果希望透明地存?Python 对象Q而不丢失其n份和cd{信息,则需要某UŞ式的对象序列化:它是一个把L复杂的对象{成对象的文本或二q制表示的过E。同P必须能够把对象经q? 序列化后的Ş式恢复到原有的对象。在 Python 中,q种序列化过E称?pickleQ可以把对象 pickle 成字W串、磁盘上的文件或者Q何类g文g的对象,也可以把q些字符丌Ӏ文件或McM于文件的对象 unpickle 成原来的对象。我们把在本文后面详l讨?pickle?

假定您喜Ƣ把M事物都保存成对象Q而且希望避免把对象{换成某种Z非对象存? 的开销Q那?pickle 文g可以提供q些好处Q但有时可能需要比q种单的 pickle 文g更健壮以及更h可׾~性的事物。例如,只用 pickle 不能解决命名和查?pickle 文gq样的问题,另外Q它也不能支持ƈ发地讉K持久性对象。如果需要这些方面的功能Q则要求助类g ZODBQ针?Python ?Z 对象数据库)q类数据库。ZODB 是一个健壮的、多用户的和面向对象的数据库pȝQ它能够存储和管理Q意复杂的 Python 对象Qƈ支持事务操作和ƈ发控制。(请参阅参考资料,以下?ZODB。)令h_感兴的是,甚至 ZODB 也依?Python 的本机序列化能力Q而且要有效地使用 ZODBQ必d分了?pickle?

另一Uo人感兴趣的解x久性问题的Ҏ?PrevaylerQ它最初是? Java 实现的(有关 Prevaylor 斚w?developerWorks 文章Q请参阅参考资料)。最q,一?Python E序员把 Prevayler ULC Python 上,另v名ؓ PyPerSystQ由 SourceForge 托管Q有兌 PyPerSyst 目的链接,请参阅参考资料)。Prevayler/PyPerSyst 概念也是建立?Java ?Python 语言的本机序列化能力之上。PyPerSyst 把整个对象系l保存在内存中,q过不时地把pȝ快照 pickle 到磁盘以及维护一个命令日志(通过此日志可以重新应用最新的快照Q来提供N恢复。所以,管使用 PyPerSyst 的应用程序受到可用内存的限制Q但好处是本机对象系l可以完全装入到内存中,因而速度极快Q而且实现h要比?ZODB q样的数据库单,ZODB 允许对象的数目比同时在能内存中所保持的对象要多?

既然我们已经要讨Z存储持久对象的各U方法,那么现在该详l探? pickle q程了。虽然我们主要感兴趣的是探烦以各U方式来保存 Python 对象Q而不必把其{换成某种其它格式Q但我们仍然q有一些需要关注的地方Q譬如:怎么h效地 pickle ?unpickle 单对象以及复杂对象,包括定制cȝ实例Q怎么L护对象的引用Q包括@环引用和递归引用Q以及怎么样处理类定义发生的变化,从而用以前经q? pickle 的实例时不会发生问题。我们把在随后关?Python ?pickle 能力探讨中涉及所有这些问题?br />

一些经q?pickle ?Python

pickle 模块及其同类模块 cPickle ?Python 提供? pickle 支持。后者是?C ~码的,它具有更好的性能Q对于大多数应用E序Q推荐用该模块。我们把l箋讨论 pickleQ但本文的示例实际是利用?cPickle。由于其中大多数CZ要用 Python shell 来显C,所以先展示一下怎么样导? cPickleQƈ可以作ؓ pickle 来引用它Q?

  >>> import cPickle as pickle

现在已经导入了该模块Q接下来让我们看一?pickle 接口。pickle 模块提供了以下函数对Qdumps(object) q回一个字W串Q它包含一?pickle 格式的对象;loads(string) q回包含? pickle 字符串中的对象;dump(object, file) 把对象写到文Ӟq个文g可以是实际的物理文gQ但也可以是McM于文件的对象Q这个对象具?write() ҎQ可以接受单个的字符串参敎ͼload(file) q回包含?pickle 文g中的对象?

~省情况下,dumps() ?dump() 使用可打印的 ASCII 表示来创?pickle。两者都有一?final 参数Q可选)Q如果ؓ TrueQ则该参数指定用更快以及更小的二q制表示来创? pickle。loads() ?load() 函数自动?pickle 是二q制格式q是文本格式?

清单 1 昄了一个交互式会话Q这里用了刚才所描述?dumps() ?loads() 函数Q?

  Welcome To PyCrust 0.7.2 - The Flakiest Python Shell
Sponsored by Orbtech - Your source for Python programming expertise.
Python 2.2.1 (#1, Aug 27 2002, 10:22:32)
[GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)] on linux-i386
Type "copyright", "credits" or "license" for more information.
>>> import cPickle as pickle
>>> t1 = ('this is a string', 42, [1, 2, 3], None)
>>> t1
('this is a string', 42, [1, 2, 3], None)
>>> p1 = pickle.dumps(t1)
>>> p1
"(S'this is a string'\nI42\n(lp1\nI1\naI2\naI3\naNtp2\n."
>>> print p1
(S'this is a string'
I42
(lp1
I1
aI2
aI3
aNtp2
.
>>> t2 = pickle.loads(p1)
>>> t2
('this is a string', 42, [1, 2, 3], None)
>>> p2 = pickle.dumps(t1, True)
>>> p2
'(U\x10this is a stringK*]q\x01(K\x01K\x02K\x03eNtq\x02.'
>>> t3 = pickle.loads(p2)
>>> t3
('this is a string', 42, [1, 2, 3], None)
清单 1. dumps() ?loads() 的演C?/center>

注:该文?pickle 格式很简单,q里׃解释了。事实上Q在 pickle 模块中记录了所有用的U定。我们还应该指出Q在我们的示例中使用的都是简单对象,因此使用二进?pickle 格式不会在节省空间上昄出太大的效率。然而,在实际用复杂对象的pȝ中,您会看到Q用二q制格式可以在大和速度斚w带来显著的改q?

接下来,我们看一些示例,q些CZ用到?dump() ? load()Q它们用文件和cM文g的对象。这些函数的操作非常cM于我们刚才所看到?dumps() ? loads()Q区别在于它们还有另一U能??dump() 函数能一个接着一个地把几个对象{储到同一个文件。随后调?load() 来以同样的顺序检索这些对象。清?2 昄了这U能力的实际应用Q?

  >>> a1 = 'apple'
>>> b1 = {1: 'One', 2: 'Two', 3: 'Three'}
>>> c1 = ['fee', 'fie', 'foe', 'fum']
>>> f1 = file('temp.pkl', 'wb')
>>> pickle.dump(a1, f1, True)
>>> pickle.dump(b1, f1, True)
>>> pickle.dump(c1, f1, True)
>>> f1.close()
>>> f2 = file('temp.pkl', 'rb')
>>> a2 = pickle.load(f2)
>>> a2
'apple'
>>> b2 = pickle.load(f2)
>>> b2
{1: 'One', 2: 'Two', 3: 'Three'}
>>> c2 = pickle.load(f2)
>>> c2
['fee', 'fie', 'foe', 'fum']
>>> f2.close()
清单 2. dump() ?load() CZ

Pickle 的威?/strong>

到目前ؓ止,我们讲述了关?pickle 斚w的基本知识。在q一节,把讨Z些高U问题,当您开?pickle 复杂对象Ӟ会遇到这些问题,其中包括定制cȝ实例。幸q的是,Python 可以很容易地处理q种情Ş?

可移植?/strong>

从空间和旉上说QPickle 是可UL的。换句话_pickle 文g格式独立于机器的体系l构Q这意味着Q例如,可以?Linux 下创Z?pickleQ然后把它发送到?Windows ?Mac OS 下运行的 Python E序。ƈ且,当升U到更新版本?Python Ӟ不必担心可能要废弃已有的 pickle。Python 开发h员已l保?pickle 格式把可以向后兼?Python 各个版本。事实上Q在 pickle 模块中提供了有关目前以及所支持的格式方面的详细信息Q?

  >>> pickle.format_version
'1.3'
>>> pickle.compatible_formats
['1.0', '1.1', '1.2']
清单 3. 索所支持的格?/center>

多个引用Q同一对象

?Python 中,变量是对象的引用。同Ӟ也可以用多个变量引用同一个对象。经证明QPython 在用l过 pickle 的对象维护这U行为方面丝毫没有困难,如清?4 所C:

  >>> a = [1, 2, 3]
>>> b = a
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>> c = pickle.dumps((a, b))
>>> d, e = pickle.loads(c)
>>> d
[1, 2, 3, 4]
>>> e
[1, 2, 3, 4]
>>> d.append(5)
>>> d
[1, 2, 3, 4, 5]
>>> e
[1, 2, 3, 4, 5]
清单 4. 对象引用的维?/center>

循环引用和递归引用

可以把刚才演C的对象引用支持扩展到循环引用Q两个对象各自包含对Ҏ的引用)和递归引用Q一个对象包含对其自w的引用Q。下面两个清单着重显CU能力。我们先看一下递归引用Q?

  >>> l = [1, 2, 3]
>>> l.append(l)
>>> l
[1, 2, 3, [...]]
>>> l[3]
[1, 2, 3, [...]]
>>> l[3][3]
[1, 2, 3, [...]]
>>> p = pickle.dumps(l)
>>> l2 = pickle.loads(p)
>>> l2
[1, 2, 3, [...]]
>>> l2[3]
[1, 2, 3, [...]]
>>> l2[3][3]
[1, 2, 3, [...]]
清单 5. 递归引用

现在Q看一个@环引用的CZQ?

  >>> a = [1, 2]
>>> b = [3, 4]
>>> a.append(b)
>>> a
[1, 2, [3, 4]]
>>> b.append(a)
>>> a
[1, 2, [3, 4, [...]]]
>>> b
[3, 4, [1, 2, [...]]]
>>> a[2]
[3, 4, [1, 2, [...]]]
>>> b[2]
[1, 2, [3, 4, [...]]]
>>> a[2] is b
1
>>> b[2] is a
1
>>> f = file('temp.pkl', 'w')
>>> pickle.dump((a, b), f)
>>> f.close()
>>> f = file('temp.pkl', 'r')
>>> c, d = pickle.load(f)
>>> f.close()
>>> c
[1, 2, [3, 4, [...]]]
>>> d
[3, 4, [1, 2, [...]]]
>>> c[2]
[3, 4, [1, 2, [...]]]
>>> d[2]
[1, 2, [3, 4, [...]]]
>>> c[2] is d
1
>>> d[2] is c
1
清单 6. 循环引用

注意Q如果分?pickle 每个对象Q而不是在一个元l中一?pickle 所有对象,会得到略微不同(但很重要Q的l果Q如清单 7 所C:

  >>> f = file('temp.pkl', 'w')
>>> pickle.dump(a, f)
>>> pickle.dump(b, f)
>>> f.close()
>>> f = file('temp.pkl', 'r')
>>> c = pickle.load(f)
>>> d = pickle.load(f)
>>> f.close()
>>> c
[1, 2, [3, 4, [...]]]
>>> d
[3, 4, [1, 2, [...]]]
>>> c[2]
[3, 4, [1, 2, [...]]]
>>> d[2]
[1, 2, [3, 4, [...]]]
>>> c[2] is d
0
>>> d[2] is c
0
清单 7. 分别 pickle vs. 在一个元l中一?pickle

相等Q但q不L相同

正如在上一个示例所暗示的,只有在这些对象引用内存中同一个对象时Q它们才是相同的。在 pickle 情Ş中,每个对象被恢复到一个与原来对象相等的对象,但不是同一个对象。换句话_每个 pickle 都是原来对象的一个副本:

  >>> j = [1, 2, 3]
>>> k = j
>>> k is j
1
>>> x = pickle.dumps(k)
>>> y = pickle.loads(x)
>>> y
[1, 2, 3]
>>> y == k
1
>>> y is k
0
>>> y is j
0
>>> k is j
1
清单 8. 作ؓ原来对象副本的被恢复的对?/center>

同时Q我们看?Python 能够l护对象之间的引用,q些对象是作Z个单元进? pickle 的。然而,我们q看到分别调?dump() 会 Python 无法l护对在该单元外部进?pickle 的对象的引用。相反,Python 复制了被引用对象Qƈ把副本和?pickle 的对象存储在一赗对?pickle 和恢复单个对象层ơ结构的应用E序Q这是没有问题的。但要意识到q有其它情Ş?

值得指出的是Q有一个选项实允许分别 pickle 对象Qƈl护怺之间的引用,只要q些对象都是 pickle 到同一文g卛_。pickle ?cPickle 模块提供了一? PicklerQ与此相对应?UnpicklerQ,它能够跟t已l被 pickle 的对象。通过使用q个 PicklerQ把会通过引用而不是通过值来 pickle ׃n和@环引用:

  >>> f = file('temp.pkl', 'w')
>>> pickler = pickle.Pickler(f)
>>> pickler.dump(a)

>>> pickler.dump(b)

>>> f.close()
>>> f = file('temp.pkl', 'r')
>>> unpickler = pickle.Unpickler(f)
>>> c = unpickler.load()
>>> d = unpickler.load()
>>> c[2]
[3, 4, [1, 2, [...]]]
>>> d[2]
[1, 2, [3, 4, [...]]]
>>> c[2] is d
1
>>> d[2] is c
1
清单 9. l护分别 pickle 的对象间的引?/center>

不可 pickle 的对?/strong>

一些对象类型是不可 pickle 的。例如,Python 不能 pickle 文g对象Q或者Q何带有对文g对象引用的对象)Q因?Python ?unpickle 时不能保证它可以重徏该文件的状态(另一个示例比较难懂,在这cL章中不值得提出来)。试?pickle 文g对象会导致以下错误:

  >>> f = file('temp.pkl', 'w')
>>> p = pickle.dumps(f)
Traceback (most recent call last):
File "", line 1, in ?
File "/usr/lib/python2.2/copy_reg.py", line 57, in _reduce
raise TypeError, "can't pickle Qs objects" Q?base.__name__
TypeError: can't pickle file objects
清单 10. 试图 pickle 文g对象的结?br />

cd?/strong>

?pickle 单对象类型相比,pickle cd例要多加留意。这主要׃ Python ?pickle 实例数据Q通常?_dict_ 属性)和类的名Uͼ而不?pickle cȝ代码。当 Python unpickle cȝ实例Ӟ它会试图使用?pickle 该实例时的确切的cdU和模块名称Q包括Q何包的\径前~Q导入包含该cd义的模块。另外要注意Q类定义必须出现在模块的最层Q这意味着它们不能是嵌? 的类Q在其它cL函数中定义的c)?

?unpickle cȝ实例Ӟ通常不会再调用它们的 _init_() Ҏ。相反,Python 创徏一个通用cd例,q应用已q行q?pickle 的实例属性,同时讄该实例的 _class_ 属性,使其指向原来的类?

?Python 2.2 中引入的新型c进?unpickle 的机制与原来的略有不同。虽然处理的l果实际上与Ҏ型类处理的结果相同,?Python 使用 copy_reg 模块?_reconstructor() 函数来恢复新型类的实例?

如果希望Ҏ型或旧型cȝ实例修改~省?pickle 行ؓQ则可以定义Ҏ的类的方?_getstate_() ?_setstate_()Q在保存和恢复类实例的状态信息期_Python 会调用这些方法。在以下几节中,我们会看C些示例利用了q些Ҏ的方法?

现在Q我们看一个简单的cd例。首先,创徏一?persist.py ?Python 模块Q它包含以下新型cȝ定义Q?

  class Foo(object):

def __init__(self, value):
self.value = value
清单 11. 新型cȝ定义

现在可以 pickle Foo 实例Qƈ看一下它的表C:

  >>> import cPickle as pickle
>>> from Orbtech.examples.persist import Foo
>>> foo = Foo('What is a Foo?')
>>> p = pickle.dumps(foo)
>>> print p
ccopy_reg
_reconstructor
p1
(cOrbtech.examples.persist
Foo
p2
c__builtin__
object
p3
NtRp4
(dp5
S'value'
p6
S'What is a Foo?'
sb.
>>>
清单 12. pickle Foo 实例

可以看到q个cȝ名称 Foo 和全限定的模块名U? Orbtech.examples.persist 都存储在 pickle 中。如果把q个实例 pickle 成一个文ӞE后? unpickle 它或在另一台机器上 unpickleQ则 Python 会试囑֯?Orbtech.examples.persist 模块Q如果不能导入,则会抛出异常。如果重命名该类和该模块或者把该模块移到另一个目录,则也会发生类似的错误?

q里有一?Python 发出错误消息的示例,当我们重命名 Foo c,然后试图装入先前q行q?pickle ?Foo 实例时会发生该错误:

  >>> import cPickle as pickle
>>> f = file('temp.pkl', 'r')
>>> foo = pickle.load(f)
Traceback (most recent call last):
File "", line 1, in ?
AttributeError: 'module' object has no attribute 'Foo'
清单 13. 试图装入一个被重命名的 Foo cȝl过 pickle 的实?/center>

在重命名 persist.py 模块之后Q也会发生类似的错误Q?

  >>> import cPickle as pickle
>>> f = file('temp.pkl', 'r')
>>> foo = pickle.load(f)
Traceback (most recent call last):
File "", line 1, in ?
ImportError: No module named persist
清单 14. 试图装入一个被重命名的 persist.py 模块的经q?pickle 的实?/center> 我们会在下面模式改进q一节提供一些技术来理q类更改Q而不会破坏现有的 pickle?br />

Ҏ的状态方?/strong>

前面提到对一些对象类型(譬如Q文件对象)不能q行 pickle。处理这U不? pickle 的对象的实例属性时可以使用Ҏ的方法(_getstate_() ?_setstate_()Q来修改cd例的状态。这里有一? Foo cȝCZQ我们已l对它进行了修改以处理文件对象属性:

  class Foo(object):

def __init__(self, value, filename):
self.value = value
self.logfile = file(filename, 'w')

def __getstate__(self):
"""Return state values to be pickled."""
f = self.logfile
return (self.value, f.name, f.tell())

def __setstate__(self, state):
"""Restore state from the unpickled state values."""
self.value, name, position = state
f = file(name, 'w')
f.seek(position)
self.logfile = f
清单 15. 处理不能 pickle 的实例属?/center>

pickle Foo 的实例时QPython 把只 pickle 当它调用该实例的 _getstate_() Ҏ时返回给它的倹{类似的Q在 unpickle ӞPython 把提供经q?unpickle 的g为参C递给实例?_setstate_() Ҏ。在 _setstate_() Ҏ内,可以Ҏl过 pickle 的名U和位置信息来重建文件对象,q把该文件对象分配给q个实例?logfile 属性?

模式改进

随着旉的推U,您会发现自己必须要更改类的定义。如果已l对某个cd例进行了 pickleQ而现在又需要更改这个类Q则您可能要索和更新那些实例Q以便它们能在新的类定义下l正常工作。而我们已l看到在对类或模块进行某些更? Ӟ会出C些错误。幸q的是,pickle ?unpickle q程提供了一?hookQ我们可以用它们来支持这U模式改q的需要?

在这一节,我们把探讨一些方法来预测常见问题以及怎么栯册些问题。由于不? pickle cd例代码,因此可以d、更改和除去ҎQ而不会媄响现有的l过 pickle 的实例。出于同L原因Q可以不必担心类的属性。您必须保包含cd义的代码模块?unpickle 环境中可用。同时还必须些可能导? unpickle 问题的更改做好规划,q些更改包括Q更改类名、添加或除去实例的属性以及改变类定义模块的名U或位置?

cd的更?/strong>

要更改类名,而不破坏先前l过 pickle 的实例,请遵循以下步骤。首先,保原来的类的定义没有被更改Q以便在 unpickle 现有实例时可以找到它。不要更改原来的名称Q而是在与原来cd义所在的同一个模块中Q创cd义的一个副本,同时l它一个新的类名。然后用实际的新类 名来替代 NewClassNameQ把以下Ҏd到原来类的定义中Q?

  def __setstate__(self, state):
self.__dict__.update(state)
self.__class__ = NewClassName
清单 16. 更改cdQ添加到原来cd义的Ҏ

?unpickle 现有实例ӞPython 把查扑֎来类的定义,q调用实例的 _setstate_() ҎQ同时把l新的类定义重新分配该实例的 _class_ 属性。一旦确定所有现有的实例都已l? unpickle、更新和重新 pickle 后,可以从源代码模块中除L的类定义?

属性的d和删?/strong>

q些Ҏ的状态方?_getstate_() ?_setstate_() 再一ơ我们能控制每个实例的状态,q我们有机会处理实例属性中的更攏V让我们看一个简单的cȝ定义Q我们把向其d和除M些属性。这是是最初的定义Q?

 class Person(object):

def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
清单 17. 最初的cd?/center>

假定已经创徏q?pickle ?Person 的实例,现在我们军_真的只想存储一个名U属性,而不是分别存储姓和名。这里有一U方式可以更改类的定义,它把先前l过 pickle 的实例迁Ud新的定义Q?

 

  class Person(object):

def __init__(self, fullname):
self.fullname = fullname

def __setstate__(self, state):
if 'fullname' not in state:
first = '
last = '
if 'firstname' in state:
first = state['firstname']
del state['firstname']
if 'lastname' in state:
last = state['lastname']
del state['lastname']
self.fullname = " ".join([first, last]).strip()
self.__dict__.update(state)
清单 18. 新的cd?/center>

在这个示例,我们d了一个新的属?fullnameQƈ除去了两个现有的属? firstname ?lastname。当对先前进行过 pickle 的实例执?unpickle Ӟ其先前进行过 pickle 的状态会作ؓ字典传递给 _setstate_()Q它把包?firstname ?lastname 属性的倹{接下来Q把q两个值组合v来,q把它们分配l新属?fullname。在q个q程中,我们删除了状态字怸旧的属性。更新和重新 pickle 先前q行q?pickle 的所有实例之后,现在可以从类定义中除?_setstate_() Ҏ?

模块的修?/strong>

在概念上Q模块的名称或位|的改变cM于类名称的改变,但处理方式却完全不同。那? 因ؓ模块的信息存储在 pickle 中,而不是通过标准?pickle 接口可以修改的属性。事实上Q改变模块信息的唯一办法是对实际? pickle 文g本n执行查找和替换操作。至于怎么L切地dQ这取决于具体的操作pȝ和可使用的工兗很昄Q在q种情况下,您会惛_份您的文Ӟ以免发生错误? 但这U改动应该非常简单,q且对二q制 pickle 格式q行更改与对文本 pickle 格式q行更改应该一h效?

l束?/strong>

对象持久性依赖于底层~程语言的对象序列化能力。对?Python 对象x味着 pickle。Python ?pickle ?Python 对象有效的持久性管理提供了健壮的和可靠的基。在下面的参考资料中Q您把会扑ֈ有关建立?Python pickle 能力之上的系l的信息?




]]>python学习W记http://m.tkk7.com/renyangok/archive/2007/09/02/142080.html保尔?/dc:creator>保尔?/author>Sun, 02 Sep 2007 08:18:00 GMThttp://m.tkk7.com/renyangok/archive/2007/09/02/142080.htmlhttp://m.tkk7.com/renyangok/comments/142080.htmlhttp://m.tkk7.com/renyangok/archive/2007/09/02/142080.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/142080.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/142080.html阅读全文

]]>
python中的unittest实例http://m.tkk7.com/renyangok/archive/2007/06/20/125259.html保尔?/dc:creator>保尔?/author>Wed, 20 Jun 2007 02:38:00 GMThttp://m.tkk7.com/renyangok/archive/2007/06/20/125259.htmlhttp://m.tkk7.com/renyangok/comments/125259.htmlhttp://m.tkk7.com/renyangok/archive/2007/06/20/125259.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/125259.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/125259.html
import unittest

def suite():
    suite = unittest.TestSuite()
    suite.addTest(JustinTest('test1'))
    suite.addTest(JustinTest('test2'))
    return suite

class JustinTest(unittest.TestCase):
    def setUp(self):
        print 'setUp'

    def tearDown(self):
        print 'tearDown'

    def test1(self):
        print 'test1'

    def test2(self):
        print 'test2'

if __name__ == '__main__':
    unittest.main(defaultTest='suite')

____________________________________________________________________________________
test 2:

import unittest

class JustinTest(unittest.TestCase):
    def setUp(self):
        print 'setUp'

    def tearDown(self):
        print 'tearDown'

    def test1(self):
        print 'test1'

    def test2(self):
        print 'test2'

class JustinTest2(unittest.TestCase):
    def setUp(self):
        print '2setUp'

    def tearDown(self):
        print '2tearDown'

    def test1(self):
        print '2test1'

    def test2(self):
        print '2test2'

if __name__ == '__main__':
    unittest.main()


]]>
Exoweb's study planhttp://m.tkk7.com/renyangok/archive/2007/04/18/111676.html保尔?/dc:creator>保尔?/author>Wed, 18 Apr 2007 08:49:00 GMThttp://m.tkk7.com/renyangok/archive/2007/04/18/111676.htmlhttp://m.tkk7.com/renyangok/comments/111676.htmlhttp://m.tkk7.com/renyangok/archive/2007/04/18/111676.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/111676.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/111676.html
Python
   http://docs.python.org/tut/tut.html
   [http://www.woodpecker.org.cn/diveintopython/toc/index.html(dive into python Chinese Edition)]
   http://www.python.org/doc/2.3.5/lib/lib.html(Python lib: sections 1, 4, 5.3, 11.4, 11.5, 11.6)
   http://www.cublog.cn/u/12592/showart.php?id=143640(regular expression)
   [http://wiki.woodpecker.org.cn/moin/PythonCodingRule(Python coding rule)]

Agile development
   http://agilemanifesto.org/principles.html
   http://www.martinfowler.com/articles/newMethodology.html
   [http://www.aka.org.cn/Docs/latest/newMethodology_Chinese.html#N301]
   http://www.controlchaos.com/

Linux
   http://www.debian.org/doc/manuals/users-guide/users-guide.en.html
   http://www.debian.org/doc/manuals/reference/reference.en.html(chapters 1-11)
   http://www.debian.org/doc/manuals/apt-howto/index.en.html
   [http://ukdebian.mirror.anlx.net/doc/user-manuals.zh-cn.html(Chinese Edition)]
   [http://vcd.gro.clinux.org/(vim document Chinese Edition)]

Postgresql
   http://www.postgresql.org/docs/8.1/static/index.html (chapters 1-3)
   [http://www.itworld21.com/docs/db/postgresql8.1/(Chinese Edition)]

HTML/CSShttp://www.china-pub.com/computers/common/info.asp?id=32815
   http://www.w3schools.com/html/ http://www.w3schools.com/css/(html and css)
   http://www.sitepronews.com/archives/2005/july/20.html(The 10 Best Resources for CSS)
   http://www.csszengarden.com (try implementing one of their designs)

Subversion
   http://svnbook.red-bean.com/ (chapters 1-4)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
step 2

Twisted (version 1.3 for now)
 http://twistedmatrix.com/trac/

Clearsilver (templating system)
 http://www.clearsilver.net/

Trac (task/bug tracking system)
 http://www.edgewall.com/trac/

For twisted, we use only the http portions (it is our webserver base)  and use the threaded model in most parts, except for the newest  portions, which work asynchronously (twisted's greatest strength).

Once you feel familiar with these technologies, feel free to  check out the source code for the Nordicbet project and install it on  your system. Familiarize yourself with the system and when you are  ready, with your mentor's assistance, pick a small task from trac to  work on.


]]>
《Twisted|络~程必备》翻?Q??/title><link>http://m.tkk7.com/renyangok/archive/2007/04/18/111631.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Wed, 18 Apr 2007 06:38:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/archive/2007/04/18/111631.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/111631.html</wfw:comment><comments>http://m.tkk7.com/renyangok/archive/2007/04/18/111631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/111631.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/111631.html</trackback:ping><description><![CDATA[感谢译?br><br>前言Qhttp://blog.csdn.net/gashero/archive/2007/01/19/1487463.aspx<br>W?章:http://blog.csdn.net/gashero/archive/2007/01/19/1487630.aspx<br>W?章:http://blog.csdn.net/gashero/archive/2007/01/19/1487664.aspx<br>W?章:http://blog.csdn.net/gashero/archive/2007/03/02/1519032.aspx<br>W?章:http://blog.csdn.net/gashero/archive/2007/03/02/1519035.aspx<br>W?章:http://blog.csdn.net/gashero/archive/2007/03/02/1519045.aspx<br><img src ="http://m.tkk7.com/renyangok/aggbug/111631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2007-04-18 14:38 <a href="http://m.tkk7.com/renyangok/archive/2007/04/18/111631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python开发编码规?/title><link>http://m.tkk7.com/renyangok/archive/2007/04/08/109214.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Sun, 08 Apr 2007 03:48:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/archive/2007/04/08/109214.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/109214.html</wfw:comment><comments>http://m.tkk7.com/renyangok/archive/2007/04/08/109214.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/109214.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/109214.html</trackback:ping><description><![CDATA[<p><span>q篇文所l出的编码约定适用于在主要?/span><span>Python</span><span>发布版本中组成标准库?/span><span>Python<span>    </span></span><span>代码Q请查阅相关的关于在</span><span>Python</span><span>?/span><span>C</span><span>实现?/span><span>C</span><span>代码风格指南的描q?/span></p> <p><span>q篇文改编?/span><span>Guido</span><span>最初的?/span><span>Python</span><span>风格指南》一文,q从?/span><span>Barry's style guide</span><span>》中d了部分内宏V在有冲H的地方Q?/span><span>Guide</span><span>的风D则应该是W合?/span><span>PEP</span><span>的意?/span><span>(</span><span>译注Q指当有冲突Ӟ应以</span><span>Guido</span><span>风格为准</span><span>)</span><span>。这?/span><span>PEP</span><span>仍然未完成</span><span>(</span><span>实际上,它可能永q都不会完成</span><span>)</span><span>?/span></p> <p><span><span>    </span></span><span>在这风格指g的一致性是重要的。在一个项目内的一致性更重要。在一个模块或函数内的一致性最重要。但最重要的是Q知道何时会不一致——有时只是没有实施风格指对{当出现疑惑Ӟq用你的最佛_断,看看别的例子Q然后决定怎样看v来更好。ƈ且要不M问!</span></p> <p><span><span>    </span></span><span>打破一条既定规则的两个好理由:</span></p> <p><span><span>(1)<span>    </span></span></span><span>当应用这个规则是导致代码可L下降,即便Ҏ人来_他已l习惯于按这条规则来阅读代码了?/span></p> <p><span><span>(2)<span>    </span></span></span><span>Z和周围的代码保持一致而打破规?/span><span>(</span><span>也许是历史原?/span><span>)</span><span>Q虽然这也是个清除其它؜q好机?/span><span>(</span><span>真正?/span><span>XP</span><span>风格</span><span>)</span><span>?/span></p> <p> </p> <p><strong><span>代码的布局</span></strong><strong></strong></p> <p><span><span>    </span></span><strong><span>~进</span></strong></p> <p><span>使用</span><span>Emacs</span><span>?/span><span>Python-mode</span><span>的默认|</span><span>4</span><span>个空g个羃q层ơ。对于确实古老的代码Q你不希望生؜乱,可以l箋使用</span><span>8</span><span>I格的制表符</span><span>(8-space tabs)</span><span>?/span><span>Emacs Python-mode</span><span>自动发现文g中主要的~进层次Q依此设定羃q参数?/span></p> <p> </p> <p><strong><span>制表W还是空?/span></strong></p> <p><span><span>    </span></span><span>永远不要L制表W和I格。最行?/span><span>Python</span><span>~进方式是仅使用I格Q其ơ是仅用制表符Q؜合着制表W和I格~进的代码将被{换成仅用空根{?/span><span>(</span><span>?/span><span>Emacs</span><span>中,选中整个~冲区,?/span><span>ESC-x</span><span>去除制表W?/span><span>)</span><span>调用</span><span>Python</span><span>命o行解释器时?/span><span>-t</span><span>选项Q可对代码中不合法得混合制表W和I格发出警告Q?/span><span>-tt</span><span>时警告将变成错误。这些选项是被高度推荐的?/span></p> <p><span><span>    </span></span><span>对于新的目Q强烈推荐仅使用I格而不是制表符。许多编辑器拥有使之易于实现的功?/span><span>(</span><span>?/span><span>Emacs</span><span>中,认</span><span>indent-tabs-mode</span><span>?/span><span>nil)</span><span>?/span></p> <p> </p> <p><strong><span>行的最大长?/span></strong></p> <p><span><span>    </span></span><span>周围仍然有许多设备被限制在每?/span><span>80</span><span>字符Q而且Q窗口限制在</span><span>80</span><span>个字W。ɞ多个窗口ƈ排放|成为可能。在q些讑֤上用默认的折叠方式看v来有点丑陋。因此,请将所有行限制在最?/span><span>79</span><span>字符</span><span>(Emacs</span><span>准确得将行限制ؓ?/span><span>80</span><span>字符</span><span>)</span><span>Q对序排放的大块文?/span><span>(</span><span>文字符串或注释</span><span>)</span><span>Q推荐将长度限制?/span><span>72</span><span>字符?/span></p> <p><span><span>    </span></span><span>折叠长行的首选方法是使用</span><span>Pyhon</span><span>支持的圆括号Q方括号和花括号内的行gl。如果需要,你可以在表达式周围增加一寚w外的圆括P但是有时使用反斜杠看h更好Q确认恰当得~进了gl的行?/span></p> <p><span><span>    </span>Emacs</span><span>?/span><span>Python-mode</span><span>正确得完成了q些。一些例子:</span></p> <p><span>#!Python</span></p> <p><span><span>    </span>class Rectangle(Blob)</span><span>Q?/span></p> <p><span><span>        </span>def __init__(self</span><span>Q?/span><span>width</span><span>Q?/span><span>height</span><span>Q?/span><span>color='black'</span><span>Q?/span><span>emphasis=None</span><span>Q?/span><span>highlight=0)</span><span>Q?/span></p> <p><span><span>            </span>if width == 0 and height == 0 and \</span></p> <p><span><span>               </span>color == 'red' and emphasis == 'strong' or \</span></p> <p><span><span>               </span>highlight > 100</span><span>Q?/span></p> <p><span><span>                </span>raise ValueError</span><span>Q?/span><span> "sorry</span><span>Q?/span><span> you lose"</span></p> <p><span><span>            </span>if width == 0 and height == 0 and (color == 'red' or</span></p> <p><span><span>                                               </span>emphasis is None)</span><span>Q?/span></p> <p><span><span>                </span>raise ValueError</span><span>Q?/span><span>"I don't think so"</span></p> <p><span><span>            </span>Blob.__init__(self</span><span>Q?/span><span>width</span><span>Q?/span><span>height</span><span>Q?/span><span>color</span><span>Q?/span><span>emphasis</span><span>Q?/span><span>highlight)</span></p> <p> </p> <p><strong><span>I</span></strong></p> <p><span><span>    </span></span><span>用两行空行分割顶层函数和cȝ定义Q类内方法的定义用单个空行分Ԍ额外的空行可被用?/span><span>(</span><span>保守?/span><span>)</span><span>分割相关函数l成的群Q在一l相关的单句中间可以省略I?/span><span>(</span><span>例如Q一l哑元素</span><span>)</span><span>?/span></p> <p><span><span>    </span></span><span>当空行用于分割方法的定义Ӟ?#8216;</span><span>class</span><span>’行和W一个方法定义之间也要有一个空行。在函数中用空行时Q请谨慎的用于表CZ个逻辑D落?/span><span>Python</span><span>接受</span><span>contol-L(</span><span>?/span><span>^L)</span><span>换页W作为空|</span><span>Emacs(</span><span>和一些打印工?/span><span>)</span><span>Q视q个字符为页面分割符Q因此在你的文g中,可以用他们来为相关片D分c?/span></p> <p> </p> <p><strong><span>~码</span></strong></p> <p><span><span>    </span>Python</span><span>核心发布中的代码必须始终使用</span><span>ASCII</span><span>?/span><span>Latin-1</span><span>~码</span><span>(</span><span>又名</span><span> ISO-8859-1)</span><span>Q?/span><span>ASCII</span><span>的文件不必有~码</span><span>cookie</span><span>Q?/span><span>Latin-1</span><span>仅当注释或文档字W串涉及作者名字需?/span><span>Latin-1</span><span>时才被用:</span></p> <p><span><span>    </span></span><span>另外使用</span><span>\x</span><span>转义字符是在字符串中包含?/span><span>ASCII(non-ASCII)</span><span>数据的首选方法?/span></p> <p><span><span>    </span></span><span>作ؓ</span><span>PEP 263</span><span>实现代码的测试套件的部分文g是个例外?/span></p> <p> </p> <p><strong><span>导入</span></strong></p> <p><span><span>    </span></span><span>通常应该在单独的行中导入</span><span>(Imports)</span><span>Q例如:</span></p> <p><span>No</span><span>Q?/span><span>import sys</span><span>Q?/span><span> os</span></p> <p><span>Yes</span><span>Q?/span><span>import sys</span></p> <p><span><span>        </span>import os</span></p> <p><span> <span>  </span></span><span>但是q样也是可以的:</span></p> <p><span><span>    </span>from types import StringType</span><span>Q?/span><span> ListType</span></p> <p><span><span>    </span>Imports </span><span>通常被放|在文g的顶部,仅在模块注释和文字W串之后Q在模块的全局变量和常量之前?/span><span>Imports</span><span>应该有顺序地成组安放Q?/span></p> <p><span>1</span><span>、标准库的导?/span><span>(Imports )</span></p> <p><span><span>    </span>2</span><span>、相关的d</span><span>(major package)</span><span>的导?/span><span>(</span><span>卻I所有的</span><span>email</span><span>包在随后导入</span><span>)</span></p> <p><span><span>    </span>3</span><span>、特定应用的导入</span><span>(imports)</span></p> <p><span><span>    </span></span><span>你应该在每组导入之间攄一个空行,对于内部包的导入是不推荐使用相对导入的,Ҏ有导入都要用包的绝对\径?/span></p> <p><span><span>    </span></span><span>从一个包含类的模块中导入cLQ通常可以写成q样Q?/span></p> <p><span><span>        </span>from MyClass import MyClass</span></p> <p><span><span>        </span>from foo.bar.YourClass import YourClass</span></p> <p><span><span>    </span></span><span>如果q样写导致了本地名字冲突Q那么就q样?/span></p> <p><span><span>        </span>import MyClass</span></p> <p><span><span>     </span> <span>  </span>import foo.bar.YourClass</span></p> <p><span><span>    </span></span><span>即?/span><span>"MyClass.MyClass"</span><span>?/span><span>"foo.bar.YourClass.YourClass"</span></p> <p> </p> <p><strong><span>表达式和语句中的I格</span></strong></p> <p><span><span>    </span>Guido</span><span>不喜Ƣ在以下地方出现I格Q?/span></p> <p><span><span>    </span></span><span>紧挨着圆括PҎ号和花括LQ如Q?/span><span>"spam( ham[ 1 ]</span><span>Q?/span><span>{ eggs</span><span>Q?/span><span>2 } )"</span><span>。要始终它写成</span><span>"spam(ham[1]</span><span>Q?/span><span>{eggs</span><span>Q?/span><span> 2})"</span><span>?/span></p> <p><span><span>    </span></span><span>紧脓在逗号Q分h冒号前的Q如Q?/span></p> <p><span><span>      </span>"if x == 4</span><span>Q?/span><span>print x</span><span>Q?/span><span>y</span><span>Q?/span><span>x</span><span>Q?/span><span>y = y</span><span>Q?/span><span>x"</span><span>。要始终它写成</span></p> <p><span><span>      </span>"if x == 4</span><span>Q?/span><span>print x</span><span>Q?/span><span>y</span><span>Q?/span><span>x</span><span>Q?/span><span>y = y</span><span>Q?/span><span>x"</span><span>?/span></p> <p><span>紧脓着函数调用的参数列表前开式括?/span><span>(open parenthesis )</span><span>的,?/span><span>"spam (1)"</span><span>。要始终它写成</span><span>"spam(1)"</span><span>?/span></p> <p><span>紧脓在烦引或切片Q开始的开式括号前的,如:</span></p> <p><span><span>     </span>"dict ['key'] = list [index]"</span><span>。要始终它写成</span><span>"dict['key'] = list[index]"</span><span>?/span></p> <p><span><span>    </span></span><span>在赋?/span><span>(</span><span>或其?/span><span>)</span><span>q算W周围的用于和其它ƈ排的一个以上的I格Q如Q?/span></p> <p><span>#!Python</span></p> <p><span><span>          </span>x= 1</span></p> <p><span><span>          </span>y= 2</span></p> <p><span><span>          </span>long_variable = 3</span></p> <p><span>要始l将它写?/span></p> <p><span>#!Python</span></p> <p><span><span>         </span>x = 1</span></p> <p><span><span>         </span>y = 2</span></p> <p><span><span>         </span>long_variable = 3</span></p> <p><span><span>    </span>(</span><span>不要对以上Q意一条和他争论—?/span><span>Guido </span><span>Lq样的风Dq?/span><span>20</span><span>q了?/span><span>)</span></p> <p> </p> <p><strong><span>其它</span></strong></p> <p><span><span>    </span></span><span>始终在这些二元运符两边攄一个空|赋?/span><span>(=)</span><span>Q?/span> <span>比较</span><span>(==</span><span>Q?/span><span><</span><span>Q?/span><span>></span><span>Q?/span><span>!=</span><span>Q?/span><span><></span><span>Q?/span><span><=</span><span>Q?/span><span><span>      </span>>=</span><span>Q?/span><span>in</span><span>Q?/span><span>not in</span><span>Q?/span><span>is</span><span>Q?/span><span>is not)</span><span>Q布运?/span><span> (and</span><span>Q?/span><span>or</span><span>Q?/span><span>not)</span><span>?/span></p> <p><span><span>    </span></span><span>按你的看法在术q算W周围插入空根{?/span> <span>始终保持二元q算W两边空格的一致?/span></p> <p><span><span>    </span></span><span>一些例子:</span></p> <p><span>#!Python</span></p> <p><span><span>          </span>i = i+1</span></p> <p><span><span>   </span><span>       </span>submitted = submitted + 1</span></p> <p><span><span>          </span>x = x*2 - 1</span></p> <p><span><span>          </span>hypot2 = x*x + y*y</span></p> <p><span><span>          </span>c = (a+b) * (a-b)</span></p> <p><span><span>          </span>c = (a + b) * (a - b)</span></p> <p><span><span>    </span></span><span>不要在用于指定关键字参数或默认参数值的</span><span>'='</span><span>号周围用空|例如Q?/span></p> <p><span>#!Python</span></p> <p><span><span>          </span>def complex(real</span><span>Q?/span><span> imag=0</span><span>?/span><span>0)</span><span>Q?/span></p> <p><span><span>              </span>return magic(r=real</span><span>Q?/span><span> i=imag)</span></p> <p><span><span>    </span></span><span>不要多条语句写在同一行上Q?/span></p> <p><span><span>          </span>No</span><span>Q?/span><span> if foo == 'blah'</span><span>Q?/span><span>do_blah_thing()</span></p> <p><span><span>          </span>Yes</span><span>Q?/span><span>if foo == 'blah'</span><span>Q?/span></p> <p><span><span>                   </span>do_blah_thing()</span></p> <p> </p> <p><span><span>          </span>No</span><span>Q?/span><span>do_one()</span><span>Q?/span><span>do_two()</span><span>Q?/span><span>do_three()</span></p> <p><span><span>          </span>Yes</span><span>Q?/span><span> do_one()</span></p> <p><span><span>               </span>do_two()</span></p> <p><span><span>              </span> do_three()</span></p> <p> </p> <p><strong><span>注释</span></strong></p> <p><span>同代码不一致的注释比没注释更差。当代码修改Ӟ始终优先更新注释</span><span>!</span><span>注释应该是完整的句子Q如果注释是一个短语或句子Q首字母应该大写Q除非他是一个以写字母开头的标识W?/span><span>(</span><span>永远不要修改标识W的大小?/span><span>)</span><span>?/span></p> <p><span><span>    </span></span><span>如果注释很短Q最好省略末句号。注释块通常׃个或多个由完整句子构成的D落l成Q每个句子应该以句号l尾。你应该在句末,句号后用两个空|以便?/span><span>Emacs</span><span>的断行和填充工作协调一致?/span></p> <p><span><span>    </span></span><span>用英语书写时Q断词和I格是可用的。非p国家?/span><span>Python</span><span>E序员:Lp书写你的注释Q除非你</span><span>120%</span><span>的确信这些代码不会被不懂你的语言的h阅读?/span></p> <p> </p> <p><strong><span>注释?/span></strong></p> <p><span><span>    </span></span><span>注释块通常应用于跟随着一?/span><span>(</span><span>或者全?/span><span>)</span><span>代码q和q些代码有着相同的羃q层ơ。注释块中每行以‘</span><span>#</span><span>’和一个空格开?/span><span>(</span><span>除非他是注释内的~进文本</span><span>)</span><span>。注释块内的D落以仅含单?#8216;</span><span>#</span><span>’的行分割。注释块上下Ҏ好有一I包围</span><span>(</span><span>或上方两行下方一行,对一个新函数定义D늚注释</span><span>)</span><span>?/span></p> <p> </p> <p><strong><span>行内注释</span></strong></p> <p><span><span>    </span></span><span>一个行内注释是和语句在同一行的注释Q行内注释应该}慎适用Q行内注释应该至用两个I格和语句分开Q它们应该以</span><span>'#'</span><span>和单个空格开始?/span></p> <p><span><span>        </span>x = x+1<span>                 </span># Increment x</span></p> <p><span><span>    </span></span><span>如果语意是很明了的,那么行内注释是不必要的,事实上是应该被移除的。不要这样写Q?/span></p> <p><span><span>        </span>x = x+1<span>                 </span># Increment x</span></p> <p><span><span>        </span>x = x+1<span>                 </span># Compensate for border</span></p> <p><span><span>    </span></span><span>但是有时Q这h有益的:</span></p> <p><span><span>        </span>x = x+1<span>                 </span># Compensate for border</span></p> <p> </p> <p><strong><span>文档字符?/span></strong></p> <p><span><span>    </span></span><span>应该一直遵守编写好的文档字W串的约?/span><span>PEP 257 [3]</span><span>。ؓ所有公共模块,函数Q类和方法编写文字W串。文字W串寚w公开的方法不是必要的Q但你应该有一个描q这个方法做什么的注释。这个注释应该在</span><span>"def"</span><span>q行后?/span></p> <p><span>PEP 257 </span><span>描述了好的文档字W串的约定。一定注意,多行文档字符串结</span><span>"""</span><span>应该单独成行Q例如:</span></p> <p><span><span>      </span>"""Return a foobang</span></p> <p><span><span>      </span>Optional plotz says to frobnicate the bizbaz first</span><span>?/span></p> <p><span><span>     </span> """</span></p> <p><span>对单行的文字符Ԍl尾?/span><span>"""</span><span>在同一行也可以?/span></p> <p><strong><span>版本注记</span></strong></p> <p><span>如果你要?/span><span>RCS</span><span>?/span><span>CVS</span><span>的杂?/span><span>(crud)</span><span>包含在你的源文g中,按如下做?/span></p> <p><span>#!Python</span></p> <p><span><span>        </span>__version__ = "$Revision</span><span>Q?/span><span> 1</span><span>?/span><span>4 $"</span></p> <p><span><span>        </span># $Source</span><span>Q?/span><span> E</span><span>Q?/span><span>/cvsroot/Python_doc/pep8</span><span>?/span><span>txt</span><span>Q?/span><span>v $</span></p> <p><span>q个行应该包含在模块的文字W串之后Q所有代码之前,上下用一个空行分剌Ӏ?/span></p> <p> </p> <p><strong><span>命名U定</span></strong></p> <p><span><span>    </span>Python</span><span>库的命名U定有点混ؕQ所以我们将永远不能使之变得完全一_不过q是有公认的命名规范的。新的模块和?/span><span>(</span><span>包括W三方的框架</span><span>)</span><span>必须W合q些标准Q但对已有的库存在不同风格的Q保持内部的一致性是首选的?/span></p> <p> </p> <p><strong><span>描述Q命名风?/span></strong></p> <p><span><span>    </span></span><span>有许多不同的命名风格。以下的有助于L认正在用的命名风格Q独立于它们的作用?/span><span><span>    </span></span><span>以下的命名风格是众所周知的:</span></p> <p><span><span>    </span>b (</span><span>单个写字母</span><span>)</span></p> <p><span><span>    </span>B (</span><span>单个大写字母</span><span>)</span></p> <p><span><span>   </span> Lowercase</span><span>Q小写)</span></p> <p><span><span>    </span>lower_case_with_underscores</span><span>Q有下划U的写Q?/span></p> <p><span><span>    </span>UPPERCASE</span><span>Q大写)</span></p> <p><span><span>    </span>UPPER_CASE_WITH_UNDERSCORES</span><span>Q有下划U的大写Q?/span></p> <p><span><span>    </span>CapitalizedWords (</span><span>?/span><span> CapWords</span><span>Q?/span><span>CamelCase</span><span>q样命名是因为可从字母的大小写分出单词。这有时也被当作</span><span>StudlyCaps</span><span>?/span></p> <p><span><span>    </span>mixedCase (</span><span>?/span><span>CapitalizedWords</span><span>的不同在于首字母写</span><span>!)</span></p> <p><span><span>    </span>Capitalized_Words_With_Underscores</span><span>Q有下划U的首字母大写)</span><span> (</span><span>丑陋</span><span>!)</span></p> <p><span><span>    </span></span><span>q有用短的特别前~相关的名字聚合在一L风格。这?/span><span>Python</span><span>中不常用Q但是出于完整性要提一下,例如Q?/span><span>os.stat()</span><span>函数q回一个元l,他的元素传统上说名如</span><span>st_mode</span><span>Q?/span><span> st_size</span><span>Q?/span><span>st_mtime</span><span>{等?/span></p> <p><span><span>    </span>X11</span><span>库的所有公开函数?/span><span>X</span><span>开头?/span><span>(</span><span>?/span><span>Python</span><span>中,q个风格通常认ؓ是不必要的,因ؓ属性和Ҏ名以对象作前~Q而函数名以模块名作前~?/span><span>)</span></p> <p><span>另外Q以下用下划U作前导或结Ҏ形式是被公认?/span><span>(</span><span>q些通常可以和Q何习惯组?/span><span>)</span><span>Q?/span></p> <p><span>_single_leading_underscore(</span><span>单个下划U作前导</span><span>)</span><span>Q弱?#8220;内部使用</span><span>(internal use)</span><span>”标志?/span><span> (</span><span>例如Q?#8220;</span><span>from M import *</span><span>”不会导入以下划线开头的对象</span><span>)</span><span>?/span></p> <p><span>single_trailing_underscore_(</span><span>单个下划U结?/span><span>)</span><span>Q?/span> <span>用于避免?/span><span>Python</span><span>关键词的冲突Q例如:“</span><span>Tkinter.Toplevel(master</span><span>Q?/span><span>class_='ClassName')</span><span>”?/span></p> <p><span><span>    </span>_double_leading_underscore(</span><span>双下划线</span><span>)</span><span>Q从</span><span>Python 1.4</span><span>起ؓcȝ有名?/span></p> <p><span><span>    </span>_double_leading_and_trailing_underscore_</span><span>Q?#8220;</span><span>magic</span><span>”对象或属性,存在于用h制的</span><span>(user-controlled)</span><span>名字I间Q例如:</span><span>_init_</span><span>Q?/span><span> _import_ </span><span>?/span><span>_file_</span><span>。有时它们被用户定义用于触发某个法行ؓ</span><span>(</span><span>例如Q运符重蝲</span><span>)</span><span>Q有时被构造器插入Q以便自׃用或Z调试。因此,在未来的版本中,构造器</span><span>(</span><span>松散得定义ؓ</span><span>Python</span><span>解释器和标准?/span><span>)</span><span>可能打算建立自己的魔法属性列表,用户代码通常应该限制这U约定作为己用。欲成ؓ构造器的一部分的用户代码可以在下滑U中l合使用短前~Q例如:</span></p> <p><span>_bobo_magic_attr__</span><span>?/span></p> <p> </p> <p><strong><span>说明Q命名约?/span></strong></p> <p><span>应避免的名字。永q不要用字符‘</span><span>l</span><span>’</span><span>(</span><span>写字母</span><span>el(</span><span>是读音Q下?/span><span>))</span><span>Q?#8216;</span><span>O</span><span>’</span><span>(</span><span>大写字母</span><span>oh)</span><span>Q或‘</span><span>I</span><span>’</span><span>(</span><span>大写字母</span><span>eye)</span><span>作ؓ单字W的变量名。在某些字体中这些字W不能与数字</span><span>1</span><span>?/span><span>0</span><span>分L。试着在?#8216;</span><span>l</span><span>’时用‘</span><span>L</span><span>’代替?/span></p> <p> </p> <p><strong><span>模块?/span></strong></p> <p><span><span>    </span></span><span>模块应该是不含下划线的,短的Q小写的名字。因为模块名被映到文g名,有些文gpȝ大小写不敏感q且截短长名字,模块名被选ؓ相当短是重要的,q在</span><span>Unix</span><span>上不是问题,但当代码传到</span><span>Mac</span><span>?/span><span>Windows</span><span>上就可能是个问题了?/span></p> <p><span> </span><span>当用</span><span>C</span><span>?/span><span>C++</span><span>~写的扩展模块有一个伴?/span><span>Python</span><span>模块提供高层</span><span>(</span><span>例如q一步的面向对象</span><span>)</span><span>接口Ӟ</span><span>C/C++</span><span>模块有下划线前导</span><span>(</span><span>如:</span><span>_socket)</span><span>?/span><span>Python</span><span>包应该是不含下划U的Q简短的Q全写的名字?/span></p> <p> </p> <p><strong><span>cd</span></strong></p> <p><span>几乎不出意料Q类名?/span><span>CapWords</span><span>U定。内部用的cd加一个前g划线?/span></p> <p> </p> <p><strong><span>异常?/span></strong></p> <p><span>如果模块Ҏ有情况定义了单个异常Q它通常被叫?#8220;</span><span>error</span><span>”?#8220;</span><span>Error</span><span>”。似乎内?/span><span>(</span><span>扩展</span><span>)</span><span>的模块?#8220;</span><span>error</span><span>”</span><span>(</span><span>例如Q?/span><span>os.error)</span><span>Q?/span><span>Python</span><span>模块通常?#8220;</span><span>Error</span><span>”</span><span> (</span><span>例如Q?/span><span>xdrlib.Error)</span><span>。趋势似乎是們֐使用</span><span>CapWords</span><span>异常名?/span></p> <p> </p> <p><strong><span>全局变量?/span></strong></p> <p><span>(</span><span>让我们祈些变量仅在一个模块的内部有意?/span><span>)</span></p> <p><span><span>    </span></span><span>q些U定和在函数中的一栗模块是被设计ؓ通过“</span><span>from M import *</span><span>”来用的Q必ȝ一个下划线作全局变量</span><span>(</span><span>及内部函数和c?/span><span>)</span><span>的前~防止其被导出</span><span>(exporting)</span><span>?/span></p> <p> </p> <p><strong><span>函数?/span></strong></p> <p><span>函数名应该ؓ写Q可能用下划UK格单词以增加可读性?/span><span>mixedCase</span><span>仅被允许用于q种风格已经占优势的上下?/span><span>(</span><span>如:</span><span>threading.py)</span><span>Q以便保持向后兼宏V?/span></p> <p> </p> <p><strong><span>Ҏ名和实例变量</span></strong></p> <p><span>q段大体上和函数相同Q通常使用写单词Q必要时用下划线分隔增加可读性。仅Z打算作ؓcȝ公共界面的内部方法和实例使用一个前g划线Q?/span><span>Python</span><span>不强制要求这P它取决于E序员是否遵守这个约定?/span></p> <p><span>使用两个前导下划U以表示cȝ有的名字Q?/span><span>Python</span><span>这些名字和cdq接在一P</span></p> <p><span>如果c?/span><span>Foo</span><span>有一个属性名?/span><span>_a</span><span>Q它不能?/span><span>Foo._a</span><span>讉K?/span><span>(</span><span>固执的用戯是可以通过</span><span>Foo._Foo__a</span><span>得到讉K权?/span><span>)</span></p> <p><span>通常双前g划线仅被用于避免含子cȝcM的属性名的名字冲H?/span></p> <p> </p> <p><strong><span>l承的设?/span></strong></p> <p><span>始终要确定一个类中的Ҏ和实例变量是否要被公开。通常Q永q不要将数据变量公开Q除非你实现的本质上只是记录Qh们几乎L更喜Ƣ代之给Z个函C为类的界?/span><span>(Python 2.2 </span><span>的一些开发者在q点上做得非常漂?/span><span>)</span><span>?/span></p> <p><span>同样Q确定你的属性是否应为私有的。私有和非私有的区别在于模板永q不会对原有的类</span><span>(</span><span>导出c?/span><span>)</span><span>有效Q而后者可以。你应该在大脑中ql承设计好了你的c,U有属性必L两个前导下划U,无后|下划线Q非公有属性必L一个前g划线Q无后置下划U,公共属性没有前导和后置下划U,除非它们与保留字冲突Q在此情况下Q单个后|下划线比前|或混ؕ的拼写要好,例如Q?/span><span>class_</span><span>优于</span><span>klass</span><span>?/span></p> <p><span>最后一Ҏ些争议:如果相比</span><span>class_</span><span>你更喜欢</span><span>klass</span><span>Q那么这只是一致性问题?/span></p> <p> </p> <p><strong><span>设计</span></strong></p> <p><span>单个元素</span><span>(singletons)</span><span>的比较,?/span><span>None </span><span>应该永远用:‘</span><span>is</span><span>’?#8216;</span><span>is not</span><span>’来做。当你本意是“</span><span>if x is not None</span><span>”Ӟ对写?#8220;</span><span>if x</span><span>”要小心。例如当你测试一个默认ؓ</span><span>None</span><span>的变量或参数是否被设|ؓ其它值时Q这个g许在布尔上下?/span><span>(Boolean context)</span><span>中是</span><span>false</span><span>Q?/span></p> <p><span>Zcȝ异常L好过Z字符串的异常。模块和包应该定义它们自q域内特定的基异常c,基类应该是内建的</span><span>Exception</span><span>cȝ子类。还始终包含一个类的文档字W串。例如:</span></p> <p><span>#!Python</span></p> <p><span><span>   </span><span>     </span>class MessageError(Exception)</span><span>Q?/span></p> <p><span><span>            </span>"""Base class for errors in the email package</span><span>?/span><span>"""</span></p> <p><span>使用字符串方?/span><span>(methods)</span><span>代替字符串模块,除非必须向后兼容</span><span>Python 2.0</span><span>以前的版本。字W串ҎL非常快,而且?/span><span>unicode</span><span>字符串共用同L</span><span>API(</span><span>应用E序接口</span><span>)</span><span>在检查前~或后~旉免对字符串进行切片。用</span><span>startswith()</span><span>?/span><span>endswith()</span><span>代替Q因为它们是明确的ƈ且错误更。例如:</span></p> <p><span><span>    </span><span>    </span>No</span><span>Q?/span><span> if foo[</span><span>Q?/span><span>3] == 'bar'</span><span>Q?/span></p> <p><span><span>        </span>Yes</span><span>Q?/span><span> if foo</span><span>?/span><span>startswith('bar')</span><span>Q?/span></p> <p><span>例外是如果你的代码必d作在</span><span>Python 1.5.2 (</span><span>但是我们希望它不会发生!</span><span>)</span><span>Q对象类型的比较应该始终?/span><span>isinstance()</span><span>代替直接比较cdQ例如:</span></p> <p><span><span>        </span>No</span><span>Q?/span><span> if type(obj) is type(1)</span><span>Q?/span></p> <p><span><span>        </span>Yes</span><span>Q?/span><span> if isinstance(obj</span><span>Q?/span><span> int)</span><span>Q?/span></p> <p><span>查一个对象是否是字符串时Q紧记它也可能是</span><span>unicode</span><span>字符Ԍ?/span><span>Python 2.3</span><span>Q?/span><span>str</span><span>?/span><span>unicode</span><span>有公q基类Q?/span><span>basestring</span><span>Q所以你可以q样做:</span></p> <p><span><span>        </span>if isinstance(obj</span><span>Q?/span><span> basestring)</span><span>Q?/span></p> <p><span>?/span><span>Python 2.2</span><span>cd模块为此定义?/span><span>StringTypes</span><span>cdQ例如:</span></p> <p><span>#!Python</span></p> <p><span><span>        </span>from types import StringTypes</span></p> <p><span><span>        </span>if isinstance(obj</span><span>Q?/span><span> StringTypes)</span><span>Q?/span></p> <p><span>?/span><span>Python 2.0</span><span>?/span><span>2.1</span><span>Q你应该q样做:</span></p> <p><span>#!Python</span></p> <p><span><span>      </span><span>  </span>from types import StringType</span><span>Q?/span><span> UnicodeType</span></p> <p><span><span>        </span>if isinstance(obj</span><span>Q?/span><span> StringType) or \</span></p> <p><span><span>           </span>isinstance(obj</span><span>Q?/span><span> UnicodeType) </span><span>Q?/span></p> <p><span>对序列,</span><span>(</span><span>字符Ԍ列表Q元l?/span><span>)</span><span>Q用空列表?/span><span>false</span><span>q个事实Q因?#8220;</span><span>if not seq</span><span>”?#8220;</span><span>if seq</span><span>”?#8220;</span><span>if len(seq)</span><span>”?#8220;</span><span>if not len(seq)</span><span>”好。书写字W串文字时不要依赖于有意义的后置I格。这U后|空格在视觉上是不可辨别的,q且有些~辑?/span><span>(</span><span>特别是近来,</span><span>reindent.py)</span><span>会将它们修整掉。不要用</span><span>==</span><span>来比较布型的g定?/span><span>True</span><span>?/span><span>False(</span><span>布尔型是</span><span>Pythn 2.3</span><span>中新增的</span><span>)</span></p> <p><span><span>        </span>No</span><span>Q?/span><span> if greeting == True</span><span>Q?/span></p> <p><span><span>        </span>Yes</span><span>Q?/span><span> if greeting</span><span>Q?/span></p> <p> </p> <p><span><span>        </span>No</span><span>Q?/span><span> if greeting == True</span><span>Q?/span></p> <p><span><span>        </span>Yes</span><span>Q?/span><span> if greeting</span><span>Q?/span></p> <img src ="http://m.tkk7.com/renyangok/aggbug/109214.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2007-04-08 11:48 <a href="http://m.tkk7.com/renyangok/archive/2007/04/08/109214.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python正则表达式操作指?/title><link>http://m.tkk7.com/renyangok/archive/2007/04/05/108806.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Thu, 05 Apr 2007 14:36:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/archive/2007/04/05/108806.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/108806.html</wfw:comment><comments>http://m.tkk7.com/renyangok/archive/2007/04/05/108806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/108806.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/108806.html</trackback:ping><description><![CDATA[<p>循序渐进Q通俗易懂Q很不错<a ><br><br></a></p> <p><a >http://net.pku.edu.cn/%7Eyhf/tao_regexps_zh.html<br></a></p><img src ="http://m.tkk7.com/renyangok/aggbug/108806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2007-04-05 22:36 <a href="http://m.tkk7.com/renyangok/archive/2007/04/05/108806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>robbing的pythonhttp://m.tkk7.com/renyangok/archive/2007/03/12/103304.html保尔?/dc:creator>保尔?/author>Mon, 12 Mar 2007 06:02:00 GMThttp://m.tkk7.com/renyangok/archive/2007/03/12/103304.htmlhttp://m.tkk7.com/renyangok/comments/103304.htmlhttp://m.tkk7.com/renyangok/archive/2007/03/12/103304.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/103304.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/103304.html     以后工作要用到pythonQ之前只知道是种成熟的动态语aQ开发效率高Q仅此而已。今天看到robbin发表的这个帖子,让我对python兴趣大增Q也军_把这门语a搞懂Q努力吧Q?br />
以下转自Q?a >http://www.javaeye.com/article/7414

我眼中的Python

pythonq种~程语言我很早就听说它了Q早?998q_我在玩Linux的时候,接触过它,但是我对python的印象仅仅停留在它是一U流行的面向对象的脚本语a的认识上?/p>

zopeQ基于python的app serverQ早?000q我已l对它如雯耳了Q但是我对zope的印象仅仅停留在它是一U类似Apache HTTPD ServerQAOL Server之类的web server上?/p>

今年ozzzzzz多次向我提到python和zopeQ听得我x都v了老茧了,dlee又徏议我开设python版面Q虽然我没有{应Q但是架不住朋友们的左劝叛_Q终I对pythonq门语言有了好奇心?/p>

几天前,当我漫不l心的浏览了python和zope的网站之后,我突然有了一U“众里寻它千癑ֺQ那人却在灯火阑珊处”的感觉Q悔不P错过了那么多ơ相逢的Z?/p>

对于软g开发,我和ozzzzzz有一个共识,是脚本解释q型语a在开发效率上q远过~译强类型语aQ从软g开发角度来_脚本语言具备天然的开发效率上的优势,q是pa的内在属性决定的?/p>

例如我们可以比较一下Web~程使用PHP和Servlet/JSPQ比较一下Windows桌面应用使用VB和VC/DelphiQ比较一下Unix环境下面Shell和C/JavaQ比较一下数据库环境下面的PL/SQL和JDBC/SQLJ?/p>

我虽然用Java开发Y件已l有5q的历史了,但是能不用Java的时候,我一定不会用Java的。如果搭Z个小型的|站Q我一定选择PHP而不是JavaQ如果针Ҏ据库的小型编E,我一定用PL/SQL而不是JavaQ如果是桌面应用Q我一定选择VB而不是JavaQ如果是Unix环境我宁愉K择shellQperl甚至PHPQ而不是Java?/p>

做ؓ一U严谨的Q编译式的,面向对象语言QJavaLl我一U须正襟危坐Q须一板一眼的按照OOAD的原则编E,才敢在键盘上敲下字符的感觉。即使编写一个最规模的E序Q我也不能够接受把所有的code塞到main里面的做法。Javag以不怒自威的威严使我不敢随意~码Q不敢玷污Java的严谨。于是我即写一个很单的JDBCE序Q也要一板一眼的try catch finallyQ一层层的处理ConnectionQPreparedStatement和ResultSet?/p>

诚然Q如果开发规模比较大的项目,或者开发自有的软g产品Q必d该按照严谨的方式Q此时Java也是最适合的语a。但是我不想zȝ那么累,很多Z不想zȝ那么累,于是大家都怀念v来脚本语a的好来。对于小规模的应用,使用脚本语言快速简单完成的事情Q当你用Java的时候,你陷入了q多的层层代码包围中厅R于是groovy出现了,bean shell出现了。大家终于明白,~译语言不是软g开发的全部Q脚本语a才是最适合E序员的语言?/p>

我喜Ƣ脚本语aQ喜Ƣ的没边QJava是我的职业,但是我从来都没有在内心深处喜Ƣ过它的语法Q我更加讨厌C++变本加厉的复杂。我钟爱的语a包括学接触的BASIC和LogoQ毕业以后才掌握的Unix Shell和PHPQPerlQPL/SQL。几乎我接触q的每种脚本语言Q我都有厚的兴和感情Q除了VBA是一个例外?/p>

看看Java里面镉K的对象,Ҏ和属性命名,看看Java~程冗长的调用语句和愚蠢的对象赋值和l常长达几十行的getter/setterQ我会时不时从心底泛h心的感觉Q虽然我l常也是q种恶心感觉的制造者。但是恶心归恶心Q我知道Java有它不可取代的作用,PHP有它无法弥补的缺陗大部分脚本语言Q包括perlQPHPQPL/SQLQVBA都不是真正意义上的面向对象编E语aQ即使包括了部分面向对象语言的特性,q注定了脚本语言不能够承担大型项目的开发,甚至也不能够充当良好的可复用的组件存在?/p>

所以我很遗憾,我欣赏PHP脚本语言的开发效率,我也ƣ赏Java的面向对象的能力Q我ƣ赏PHP的低部v成本高可靠运行,我也ƣ赏Java App Server带来的开发复杂运的强大能力Q但是鱼与熊掌不可得兹{?/p>

直到我看Cpython和zopeQ我l于扑ֈ了梦寐以求的东西Q兼有脚本语a开发的高效率,兼有低部|成本的易用性,同时又有完备的面向对象的强大支撑能力Q同时又具备完善的强大的app server支持。最令我生气的还是ploneQ这个运行在zope之上的YӞ你可以称之ؓportalQ或者称之ؓcmsQ或者其他的什么名词,但是我知道它几乎可以实现M|站惌实现的功能。默认安装下Q这个东西很像confluenceQ一个Java的商业的cmsQ但是比confluence功能强大的太多,可定制性,可开发性又强的太多了。plone在默认安装情况下你就可以把它当做cms来用Q比较类?**nukecY?PHPNuke, PostNuke, JBossNuke,...)Q通过插g的扩展,你可以让plone里面集成了forumQblogQwiki的功能,再加上plone本来支持的WebDAVQ功能强大的Z文档的权限控Ӟ多用户多l的理Q你可以在很短的旉内实C个全功能的门L站。可W的是,我从dCq一直在考虑把JavaEye成ؓ一个集成forumQblogQwikiQcms功能的网站,甚至雄心壮志的想要做一个这么的软g产品来,但是现在我发现plone已经漂亮的实Cq一切,最令我沮的是Qozzzzzz在听q我的Y件品计划之后提Z个用关键词来l织|站内容的设惻Il果我发现plone已经q样做了Q我能说的只有惭愧!

我只能感叹自己没有在一q之前就发现ploneQ否则的话现在的JavaEye完整的使用plone来架设。更令我惭愧的是Q当我刚刚意识到zope/plone的h值的时候,上v已经有h成立了专业的zope/plone解决Ҏ的Y件厂商,q且拿下了好几个大型的客P(http://www.zopechina.com)。有时候我们真的不能把眼睛盲目的盯着大厂商强行推q的标准了,应该好好的审视自q正需要的是什么,q且围绕它构q核心竞争力,否则我们只有永远做IT行业食物链最底层的命q?/p>

ozzzzzz曄Ҏ_zope是B/S应用中的VBQ快速原型开发中型企业应用的最x器,我现在真切的理解了他的话。我觉得我们实不能够眼睛光盯着Java/C#不放Q也应该了解一下zope/ploneQ它应该成ؓ中小型企业应用,特别是基于文档管理的企业应用的最重要的解x案?/p>

zope/plone虽然很好Q但是我知道它不会如Java/J2EEQC#/dotnet那样在国内成ZU主的软g开发解x案。原因就在于国内的Y件开发行业长期处于国际分工业链的底层,~Z创新意识和开拓的_Q而往往满于跟随跨国公司的标准Q啃啃h家剩下的肉骨头。位于食物链层的厂商,例如MSQIBMQSunQBEAQCAQOracle{等Q争夺的是标准。他们是规则的制订者,制订好了规则Q放大家q场Q他们负责收费,钱收的差不多了的时候,他们又重新竞争,制订C轮的规则Ql坐地收贏V很多时候,市场的真实需求ƈ没有被真实的体现Q真实的需求被厂商掩盖了。他们创造了一个市场需求,有了市场需求,有pQ赚的差不多了,摧毁这个市场,然后创造下一个市场需求。因此本质上来说QIT行业是几个寡头在博弈,不管谁赢谁输Q我们都是输Ӟ我们只是人家的筹码。大家可以回一下这些年软g技术发展的历程Q寡头厂商制造了EJB市场赚大发了Q寡头厂商了刉了ERP市场赚大发了Q寡头厂商l在刉着SOAQ等着l箋攉。我们不能够被满天飞的技术迷惑了Q我们不能被人卖了还替h家数钱?/p>

所以多多关注一下我们真正需要的技术吧?/p>

]]>
Python的历?/title><link>http://m.tkk7.com/renyangok/archive/2007/03/08/102549.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Thu, 08 Mar 2007 02:19:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/archive/2007/03/08/102549.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/102549.html</wfw:comment><comments>http://m.tkk7.com/renyangok/archive/2007/03/08/102549.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/102549.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/102549.html</trackback:ping><description><![CDATA[Python的创始h为Guido van Rossum?989q圣诞节期间Q在阿姆斯特丹,GuidoZ打发圣诞节的无趣Q决心开发一个新的脚本解释程序,做ؓABC语言的一Uѝ之所以选中PythonQ大蟒蛇的意思)作ؓE序的名字,是因Z是一个Monty 大蟒蛇飞行马戏团的爱好者?<br /><br />ABC是由Guido参加设计的一U教学语aQ没听说q)。就Guido本h看来QABCq种语言非常优美和强大,是专门ؓ非专业程序员设计的。但是ABC语言q没有成功,I其原因QGuido认ؓ是非开N成的。Guido军_在Python中避免这一错误Q的如此,Python与其它的语言如C,C++和Javal合的非常好Q。同Ӟ他还惛_现在ABC中闪现过但未曑֮现的东西?<br /><br />pPPython在Guido手中诞生了(真要感谢他)。实际上Q第一个实现是在MacZ。可以说QPython是从ABC发展hQ主要受CModula-3Q另一U相当优且强大的语aQؓ型团体所设计的)的媄响。ƈ且结合了Unix Shell和C的习惯?<br /><br />Python的特?<br />Python是一U脚本语aQ它的语法表达优易诅R它h很多优秀的脚本语a的特点:解释的,面向对象的,内徏的高U数据结构,支持模块和包Q支持多U^収ͼ可扩展。而且它还支持交互式方式运行,囑Ş方式q行。它的语法有很多与众不同的特性。下面我分别说明一下: <br /><br />q行方式 <br />Python可以以命令行方式q行Q也可以交互式方式运行,q具有图形集成环境,q样开发Pythonq当方ѝ现在已l出C许多用Python~写的可视化~程软gQ用于实现象Delphi一L功能?<br />面向对象 <br />Python是一个真正的面向对象语言。它甚至支持异常的处理。如果学qJavaQ应该对q个不陌生。但其它的脚本语aQ如PHPQ好象就没有。这使得E序的编写更加清晎ͼ而不需要许多的错误查了?<br />模块和包 <br />q一Ҏ象是Java。对于Java的支持,大家可以了解JPython。JPython是用Java写的PythonQ它完全支持JavaQ在q个环境下用Python可以随意C用Java的类库?<br />语言扩展 <br />可以用C、C++或Java为Python~写新的新言模块Q如函数。或者与Python直接~译在一P或者采用动态库装入方式实现。也专门有h~写了一个工P可以实现为Python自动实现函数接口装Q这是SWIGQSimplified Wrapper and Interface Generator)Q或U做单封装和接口生成?可以?<a title="http://www.cs.utah.edu/~beazley/SWIG" target="_blank">http://www.cs.utah.edu/~beazley/SWIG</a> 自由获得)?<br />有趣的语?<br />Guido认ؓPython的语法是非常优美的。其中一点就是,块语句的表示不是C语言常用的{}对,或其它符号对Q而是采用~近表示法!有趣吧。就q一Ҏ_Guido的解释是Q首先,使用~近表示法减了视觉上的混ؕQƈ且ɽE序变短Q这样就减少了需要对基本代码单元注意的范_其次Q它减少了程序员的自由度Q更有利于统一风格Q得阅d人的E序更容易。感觉还是不错的Q就C语言来说Q在if语句后面大括L写法好几种Q不同的人喜Ƣ不同的样子Q还不如l一hQ都不会看得别扭?<br /><br />在每个类或函数的定义后面Q第一行可以是说明语句Q根本不需要注释符标记。对于后面跟块语句的语句Q后面应跟上一个冒?:)。一行语句不能太长,因ؓ没有行结束符Q如果超长则要用箋行符(\)。还有一些有的比如_象下面的一个比较处理,用C语言为: <br /><br />if (2<a && a<5) <br /><br />用Python可以表示?<br /><br />if (2<a<5) : <br /><br />当然不一定会有什么好处,但是它所宣称的优的语言毕竟不是虚的。其它的大家可以通过学习自行了解?<br />Python可以做什么? <br />那么Python可以做什么呢Q我感觉Q什么都可以。如果在Windows下,如果惛_一个图形界面程序,那么Python可以胜Q。可以去wxPython.org看一下,它是一个Python的扩展库Q可以用来实现跨q_的图形编E,它支持windows和unix/linux。在那个|站上有一些演C,可以学习一下。Python可以做CGI。有些主|供了对Python的CGI支持。现在还有一些用Python做的游戏。如果想了解更多的Python可以做什么,可以去SourceForge上查找有关Python的项目,上面有很多东ѝ?<br /><br />l束 <br />在中国Pythonq处于v步,学习研究它的人很,希望感兴的同志加入q一行列?<br /><br />参考文献:什么是PythonQ?br /><br />官方|站 <a title="http://www.python.org" target="_blank">http://www.python.org/</a><img src ="http://m.tkk7.com/renyangok/aggbug/102549.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2007-03-08 10:19 <a href="http://m.tkk7.com/renyangok/archive/2007/03/08/102549.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://shbailongma.com" target="_blank">AƬƵWWW</a>| <a href="http://fns92.com" target="_blank">òƵƽ̨</a>| <a href="http://jpsp8.com" target="_blank">Ļ޾Ʒһ</a>| <a href="http://927ff.com" target="_blank"> С˵ۺͼ</a>| <a href="http://xy996688.com" target="_blank">۲Ƶwwwѿ</a>| <a href="http://milbolg.com" target="_blank">޹ҹƷƬ</a>| <a href="http://jcthbank.com" target="_blank">Ѵվ߹</a>| <a href="http://zbvip888.com" target="_blank">ĻѸ</a>| <a href="http://6006284.com" target="_blank">޾ƷþþþYW</a>| <a href="http://www-66409b.com" target="_blank">ҹþþӰԺ</a>| <a href="http://yuduruizhi.com" target="_blank">һѹۿߵӰ </a>| <a href="http://msjdyd.com" target="_blank">Ļߵ</a>| <a href="http://abab14.com" target="_blank"></a>| <a href="http://adcadm.com" target="_blank">ˬˬƬav </a>| <a href="http://kssijia.com" target="_blank">ëƬպëƬ</a>| <a href="http://dnf1000.com" target="_blank">߲Ƶ</a>| <a href="http://t66ycom.com" target="_blank">˿Ƶ</a>| <a href="http://sdzsx.com" target="_blank">ĻѸƵ </a>| <a href="http://sh-shule.com" target="_blank">ѹۿƵ</a>| <a href="http://a666999.com" target="_blank">޹˾þһ </a>| <a href="http://868664.com" target="_blank">182tvƵ߹ۿ</a>| <a href="http://ryhjled.com" target="_blank">AVɫ߹ۿ</a>| <a href="http://wwwby1378.com" target="_blank">һۺϾþ</a>| <a href="http://aaaaa123.com" target="_blank">AVרպ</a>| <a href="http://iguasheng.com" target="_blank">ŮҹëƬƵ</a>| <a href="http://zfzz008.com" target="_blank">þþþþһƷƷѿ</a>| <a href="http://57798b.com" target="_blank">鶹va߾ƷѲ</a>| <a href="http://jiujiujingpin.com" target="_blank">޹ֻߵӰbd</a>| <a href="http://wwwse09.com" target="_blank">˾þô߽</a>| <a href="http://ur5r2kr.com" target="_blank">߿Ƭ˳Ƶڵ</a>| <a href="http://6878vip.com" target="_blank">պƷþþþþ</a>| <a href="http://www-887234.com" target="_blank">һ˿wwwѸ</a>| <a href="http://8xcb.com" target="_blank">hairyëpicsȫ</a>| <a href="http://txa6.com" target="_blank">ۺĻ</a>| <a href="http://18yinren.com" target="_blank">ŷպ</a>| <a href="http://9522952.com" target="_blank">͵͵ͼƬ</a>| <a href="http://chinacry.com" target="_blank">߹ۿ޳</a>| <a href="http://9522952.com" target="_blank">ҹպһ</a>| <a href="http://tv787.com" target="_blank">AV߹ۿɫ</a>| <a href="http://7778tv.com" target="_blank">ձ˳ɻҳ߹ۿƵ</a>| <a href="http://chaikexin.com" target="_blank">þùƵ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>