﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-路漫漫其修远兮，吾将上下而求索</title><link>http://www.blogjava.net/fhtdy2004/</link><description>经验浅薄，耐心积累；记性不好，记诸文字</description><language>zh-cn</language><lastBuildDate>Mon, 04 May 2026 23:15:57 GMT</lastBuildDate><pubDate>Mon, 04 May 2026 23:15:57 GMT</pubDate><ttl>60</ttl><item><title>Python学习笔记（二）</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292232.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Sat, 22 Aug 2009 15:48:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292232.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/292232.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292232.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/292232.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/292232.html</trackback:ping><description><![CDATA[<p>python 异常、正则表达式<br />
<a href="http://docs.python.org/library/re.html">http://docs.python.org/library/re.html</a><br />
<a href="http://docs.python.org/howto/regex.html#regex-howto">http://docs.python.org/howto/regex.html#regex-howto</a><br />
<br />
例 6.1. 打开一个不存在的文件<br />
&gt;&gt;&gt; fsock = open("/notthere", "r")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
Traceback (innermost last):<br />
&nbsp; File "&lt;interactive input&gt;", line 1, in ?<br />
IOError: [Errno 2] No such file or directory: '/notthere'<br />
&gt;&gt;&gt; try:<br />
...&nbsp;&nbsp;&nbsp;&nbsp; fsock = open("/notthere")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
... except IOError:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
...&nbsp;&nbsp;&nbsp;&nbsp; print "The file does not exist, exiting gracefully"<br />
... print "This line will always print" <br />
The file does not exist, exiting gracefully<br />
This line will always print</p>
<p><br />
# Bind the name getpass to the appropriate function<br />
&nbsp; try:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; import termios, TERMIOS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; except ImportError:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; import msvcrt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except ImportError:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from EasyDialogs import AskPassword <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; except ImportError:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getpass = default_getpass&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getpass = AskPassword<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getpass = win_getpass<br />
&nbsp; else:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getpass = unix_getpass</p>
<p>&nbsp;</p>
<p>例 6.10. 遍历 dictionary<br />
&gt;&gt;&gt; import os<br />
&gt;&gt;&gt; for k, v in os.environ.items():&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
...&nbsp;&nbsp;&nbsp;&nbsp; print "%s=%s" % (k, v)<br />
USERPROFILE=C:\Documents and Settings\mpilgrim<br />
OS=Windows_NT<br />
COMPUTERNAME=MPILGRIM<br />
USERNAME=mpilgrim</p>
<p>[...略...]<br />
&gt;&gt;&gt; print "\n".join(["%s=%s" % (k, v)<br />
...&nbsp;&nbsp;&nbsp;&nbsp; for k, v in os.environ.items()]) <br />
USERPROFILE=C:\Documents and Settings\mpilgrim<br />
OS=Windows_NT<br />
COMPUTERNAME=MPILGRIM</p>
<p>&nbsp;</p>
<p>例 6.13. 使用 sys.modules<br />
&gt;&gt;&gt; import fileinfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&gt;&gt;&gt; print '\n'.join(sys.modules.keys())<br />
win32api<br />
os.path<br />
os<br />
fileinfo<br />
exceptions</p>
<p>&gt;&gt;&gt; fileinfo<br />
&lt;module 'fileinfo' from 'fileinfo.pyc'&gt;<br />
&gt;&gt;&gt; sys.modules["fileinfo"] <br />
&lt;module 'fileinfo' from 'fileinfo.pyc'&gt;</p>
<p><br />
下面的例子将展示通过结合使用 __module__ 类属性和 sys.modules dictionary 来获取已知类所在的模块。 </p>
<p>例 6.14. __module__ 类属性 <br />
&gt;&gt;&gt; from fileinfo import MP3FileInfo<br />
&gt;&gt;&gt; MP3FileInfo.__module__&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
'fileinfo'<br />
&gt;&gt;&gt; sys.modules[MP3FileInfo.__module__] <br />
&lt;module 'fileinfo' from 'fileinfo.pyc'&gt;&nbsp; 每个 Python 类都拥有一个内置的类属性 __module__，它定义了这个类的模块的名字。&nbsp; <br />
&nbsp; 将它与 sys.modules 字典复合使用，你可以得到定义了某个类的模块的引用。&nbsp; </p>
<p>&nbsp;</p>
<p>例 6.16. 构造路径名<br />
&gt;&gt;&gt; import os<br />
&gt;&gt;&gt; os.path.join("c:\\music\\ap\\", "mahadeva.mp3")&nbsp; <br />
'c:\\music\\ap\\mahadeva.mp3'<br />
&gt;&gt;&gt; os.path.join("c:\\music\\ap", "mahadeva.mp3")&nbsp;&nbsp; <br />
'c:\\music\\ap\\mahadeva.mp3'<br />
&gt;&gt;&gt; os.path.expanduser("~")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
'c:\\Documents and Settings\\mpilgrim\\My Documents'<br />
&gt;&gt;&gt; os.path.join(os.path.expanduser("~"), "Python") <br />
'c:\\Documents and Settings\\mpilgrim\\My Documents\\Python'</p>
<p>&nbsp;</p>
<p>例 7.2. 匹配整个单词<br />
&gt;&gt;&gt; s = '100 BROAD'<br />
&gt;&gt;&gt; re.sub('ROAD$', 'RD.', s)<br />
'100 BRD.'<br />
&gt;&gt;&gt; re.sub('\\bROAD$', 'RD.', s)&nbsp; <br />
'100 BROAD'<br />
&gt;&gt;&gt; re.sub(r'\bROAD$', 'RD.', s)&nbsp; <br />
'100 BROAD'<br />
&gt;&gt;&gt; s = '100 BROAD ROAD APT. 3'<br />
&gt;&gt;&gt; re.sub(r'\bROAD$', 'RD.', s)&nbsp; <br />
'100 BROAD ROAD APT. 3'<br />
&gt;&gt;&gt; re.sub(r'\bROAD\b', 'RD.', s) <br />
'100 BROAD RD. APT 3'</p>
<p>我真正想要做的是，当 'ROAD' 出现在字符串的末尾，并且是作为一个独立的单词时，而不是一些长单词的一部分，才对他进行匹配。为了在正则表达式中表达这个意思，你利用 \b，它的含义是&#8220;单词的边界必须在这里&#8221;。在 Python 中，由于字符 '\' 在一个字符串中必须转义，这会变得非常麻烦。有时候，这类问题被称为&#8220;反斜线灾难&#8221;，这也是 Perl 中正则表达式比 Python 的正则表达式要相对容易的原因之一。另一方面，Perl 也混淆了正则表达式和其他语法，因此，如果你发现一个 bug，很难弄清楚究竟是一个语法错误，还是一个正则表达式错误。&nbsp; <br />
&nbsp; 为了避免反斜线灾难，你可以利用所谓的&#8220;原始字符串&#8221;，只要为字符串添加一个前缀 r 就可以了。这将告诉 Python，字符串中的所有字符都不转义；'\t' 是一个制表符，而 r'\t' 是一个真正的反斜线字符 '\'，紧跟着一个字母 't'。我推荐只要处理正则表达式，就使用原始字符串；否则，事情会很快变得混乱 (并且正则表达式自己也会很快被自己搞乱了)。&nbsp; </p>
<p>&nbsp;</p>
<p>例 7.4. 检验百位数<br />
&gt;&gt;&gt; import re<br />
&gt;&gt;&gt; pattern = '^M?M?M?(CM|CD|D?C?C?C?)$' <br />
&gt;&gt;&gt; re.search(pattern, 'MCM')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;SRE_Match object at 01070390&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MD')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;SRE_Match object at 01073A50&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MMMCCC')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;SRE_Match object at 010748A8&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MCMC')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&gt;&gt;&gt; re.search(pattern, '')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;SRE_Match object at 01071D98&gt;</p>
<p>&nbsp;</p>
<p>例 7.5. 老方法：每一个字符都是可选的<br />
&gt;&gt;&gt; import re<br />
&gt;&gt;&gt; pattern = '^M?M?M?$'<br />
&gt;&gt;&gt; re.search(pattern, 'M')&nbsp;&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EE090&gt;<br />
&gt;&gt;&gt; pattern = '^M?M?M?$'<br />
&gt;&gt;&gt; re.search(pattern, 'MM')&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;<br />
&gt;&gt;&gt; pattern = '^M?M?M?$'<br />
&gt;&gt;&gt; re.search(pattern, 'MMM')&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EE090&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MMMM') <br />
&gt;&gt;&gt; </p>
<p><br />
例 7.6. 一个新的方法：从 n 到 m<br />
&gt;&gt;&gt; pattern = '^M{0,3}$'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&gt;&gt;&gt; re.search(pattern, 'M')&nbsp;&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MM')&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EE090&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MMM')&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEDA8&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MMMM') <br />
&gt;&gt;&gt; </p>
<p><br />
对于个位数的正则表达式有类似的表达方式，我将省略细节，直接展示结果。</p>
<p>&gt;&gt;&gt; pattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'<br />
用另一种 {n,m} 语法表达这个正则表达式会如何呢？这个例子展示新的语法。 </p>
<p>例 7.8. 用 {n,m} 语法确认罗马数字 <br />
&gt;&gt;&gt; pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'<br />
&gt;&gt;&gt; re.search(pattern, 'MDLV')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MMDCLXVI')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;</p>
<p><br />
例 7.9. 带有内联注释 (Inline Comments) 的正则表达式<br />
&gt;&gt;&gt; pattern = """<br />
&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # beginning of string<br />
&nbsp;&nbsp;&nbsp; M{0,3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # thousands - 0 to 3 M's<br />
&nbsp;&nbsp;&nbsp; (CM|CD|D?C{0,3})&nbsp;&nbsp;&nbsp; # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or 500-800 (D, followed by 0 to 3 C's)<br />
&nbsp;&nbsp;&nbsp; (XC|XL|L?X{0,3})&nbsp;&nbsp;&nbsp; # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or 50-80 (L, followed by 0 to 3 X's)<br />
&nbsp;&nbsp;&nbsp; (IX|IV|V?I{0,3})&nbsp;&nbsp;&nbsp; # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; or 5-8 (V, followed by 0 to 3 I's)<br />
&nbsp;&nbsp;&nbsp; $&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # end of string<br />
&nbsp;&nbsp;&nbsp; """<br />
&gt;&gt;&gt; re.search(pattern, 'M', re.VERBOSE)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MCMLXXXIX', re.VERBOSE)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'MMMDCCCLXXXVIII', re.VERBOSE)&nbsp; <br />
&lt;_sre.SRE_Match object at 0x008EEB48&gt;<br />
&gt;&gt;&gt; re.search(pattern, 'M')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; 当使用松散正则表达式时，最重要的一件事情就是：必须传递一个额外的参数 re.VERBOSE，该参数是定义在 re 模块中的一个常量，标志着待匹配的正则表达式是一个松散正则表达式。正如你看到的，这个模式中，有很多空格 (所有的空格都被忽略)，和几个注释 (所有的注释也被忽略)。如果忽略所有的空格和注释，它就和前面章节里的正则表达式完全相同，但是具有更好的可读性。&nbsp; <br />
&gt;&gt;&gt; re.search(pattern, 'M')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
这个没有匹配。为什么呢？因为没有 re.VERBOSE 标记，所以 re.search 函数把模式作为一个紧凑正则表达式进行匹配。Python 不能自动检测一个正则表达式是为松散类型还是紧凑类型。Python 默认每一个正则表达式都是紧凑类型的，除非你显式地标明一个正则表达式为松散类型。 </p>
<p>&nbsp;</p>
<p>例 7.16. 解析电话号码 (最终版本)<br />
&gt;&gt;&gt; phonePattern = re.compile(r'''<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # don't match beginning of string, number can start anywhere<br />
&nbsp;&nbsp;&nbsp; (\d{3})&nbsp;&nbsp;&nbsp;&nbsp; # area code is 3 digits (e.g. '800')<br />
&nbsp;&nbsp;&nbsp; \D*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # optional separator is any number of non-digits<br />
&nbsp;&nbsp;&nbsp; (\d{3})&nbsp;&nbsp;&nbsp;&nbsp; # trunk is 3 digits (e.g. '555')<br />
&nbsp;&nbsp;&nbsp; \D*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # optional separator<br />
&nbsp;&nbsp;&nbsp; (\d{4})&nbsp;&nbsp;&nbsp;&nbsp; # rest of number is 4 digits (e.g. '1212')<br />
&nbsp;&nbsp;&nbsp; \D*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # optional separator<br />
&nbsp;&nbsp;&nbsp; (\d*)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # extension is optional and can be any number of digits<br />
&nbsp;&nbsp;&nbsp; $&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # end of string<br />
&nbsp;&nbsp;&nbsp; ''', re.VERBOSE)<br />
&gt;&gt;&gt; phonePattern.search('work 1-(800) 555.1212 #1234').groups()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
('800', '555', '1212', '1234')<br />
&gt;&gt;&gt; phonePattern.search('800-555-1212')&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
('800', '555', '1212', '')</p>
<p>&nbsp;</p>
<p><br />
现在，你应该熟悉下列技巧：</p>
<p>^ 匹配字符串的开始。 <br />
$ 匹配字符串的结尾。 <br />
\b 匹配一个单词的边界。 <br />
\d 匹配任意数字。 <br />
\D 匹配任意非数字字符。 <br />
x? 匹配一个可选的 x 字符 (换言之，它匹配 1 次或者 0 次 x 字符)。 <br />
x* 匹配0次或者多次 x 字符。 <br />
x+ 匹配1次或者多次 x 字符。 <br />
x{n,m} 匹配 x 字符，至少 n 次，至多 m 次。 <br />
(a|b|c) 要么匹配 a，要么匹配 b，要么匹配 c。 <br />
(x) 一般情况下表示一个记忆组 (remembered group)。你可以利用 re.search 函数返回对象的 groups() 函数获取它的值。 <br />
<br />
http://www.woodpecker.org.cn/diveintopython/regular_expressions/phone_numbers.html<br />
<br />
<table style="width: 802px; height: 1872px" cellspacing="0" cellpadding="1" width="802" border="1">
    <caption>
    <h5 class="docTableTitle">Regular expression pattern syntax</h5>
    </caption>
    <colgroup span="2">
    <tbody>
        <tr>
            <th class="docTableHeader">
            <p class="docText">Element</p>
            </th>
            <th class="docTableHeader">
            <p class="docText">Meaning</p>
            </th>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5256"></a><a name="pythonian-CHP-9-ITERM-5257"></a>
            <pre>.</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches any character except <tt>\n</tt> (if <tt>DOTALL</tt>, also matches <tt>\n</tt>)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5258"></a><a name="pythonian-CHP-9-ITERM-5259"></a>
            <pre>^</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches start of string (if <tt>MULTILINE</tt>, also matches after <tt>\n</tt>)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5260"></a><a name="pythonian-CHP-9-ITERM-5261"></a>
            <pre>$</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches end of string (if <tt>MULTILINE</tt>, also matches before <tt>\n</tt>)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5262"></a><a name="pythonian-CHP-9-ITERM-5263"></a>
            <pre>*</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches zero or more cases of the previous regular expression; greedy (match as many as possible)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5264"></a><a name="pythonian-CHP-9-ITERM-5265"></a>
            <pre>+</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches one or more cases of the previous regular expression; greedy (match as many as possible)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5266"></a><a name="pythonian-CHP-9-ITERM-5267"></a>
            <pre>?</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches zero or one case of the previous regular expression; greedy (match one if possible)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <p class="docText"><tt>*?</tt><a name="pythonian-CHP-9-ITERM-5268"></a> <a name="pythonian-CHP-9-ITERM-5269"></a><a name="pythonian-CHP-9-ITERM-5270"></a><a name="pythonian-CHP-9-ITERM-5271"></a>, <tt>+?</tt>, <tt>??</tt></p>
            </td>
            <td class="docTableCell">
            <p class="docText">Non-greedy versions of <tt>*</tt>, <tt>+</tt>, and <tt>?</tt> (match as few as possible)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>{<tt><em>m</em></tt>,<tt><em>n</em></tt>}</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches <tt><em>m</em></tt> to <tt><em>n</em></tt> cases of the previous regular expression (greedy)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>{<tt><em>m</em></tt>,<tt><em>n</em></tt>}?</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches <tt><em>m</em></tt> to <tt><em>n</em></tt> cases of the previous regular expression (non-greedy)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5272"></a><a name="pythonian-CHP-9-ITERM-5273"></a>
            <pre>[...]</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches any one of a set of characters contained within the brackets</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5274"></a><a name="pythonian-CHP-9-ITERM-5275"></a>
            <pre>|</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches expression either preceding it or following it</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell"><a name="pythonian-CHP-9-ITERM-5276"></a><a name="pythonian-CHP-9-ITERM-5277"></a>
            <pre>(...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches the regular expression within the parentheses and also indicates a group</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?iLmsux)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Alternate way to set optional flags; no effect on match</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?:...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Like <tt>(...)</tt>, but does not indicate a group</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?P&lt;<tt><em>id</em></tt>&gt;...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Like <tt>(...)</tt>, but the group also gets the name <tt><em>id</em></tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?P=<tt><em>id</em></tt>)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches whatever was previously matched by group named <tt><em>id</em></tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?#...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Content of parentheses is just a comment; no effect on match</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?=...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Lookahead assertion; matches if regular expression <tt>..</tt>. matches what comes next, but does not consume any part of the string</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?!...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Negative lookahead assertion; matches if regular expression <tt>..</tt>. does not match what comes next, and does not consume any part of the string</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?&lt;=...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Lookbehind assertion; matches if there is a match for regular expression <tt>..</tt>. ending at the current position (<tt>..</tt>. must match a fixed length)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>(?&lt;!...)</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Negative lookbehind assertion; matches if there is no match for regular expression <tt>..</tt>. ending at the current position (<tt>..</tt>. must match a fixed length)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\<tt><em>number</em></tt></pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches whatever was previously matched by group numbered <tt><em>number</em></tt> (groups are automatically numbered from 1 up to 99)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\A</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches an empty string, but only at the start of the whole string</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\b</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches an empty string, but only at the start or end of a word (a maximal sequence of alphanumeric characters; see also <tt>\w</tt>)</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\B</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches an empty string, but not at the start or end of a word</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <p class="docText">\d</p>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches one digit, like the set <tt>[0-9]</tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\D</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches one non-digit, like the set <tt>[^0-9]</tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\s</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches a whitespace character, like the set <tt>[</tt> <tt>\t\n\r\f\v]</tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\S</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches a non-white character, like the set <tt>[^</tt> <tt>\t\n\r\f\v]</tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\w</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches one alphanumeric character; unless <tt>LOCALE</tt> or <tt>UNICODE</tt> is set, <tt>\w</tt> is like <tt>[a-zA-Z0-9_]</tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\W</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches one non-alphanumeric character, the reverse of <tt>\w</tt></p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\Z</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches an empty string, but only at the end of the whole string</p>
            </td>
        </tr>
        <tr>
            <td class="docTableCell">
            <pre>\\</pre>
            </td>
            <td class="docTableCell">
            <p class="docText">Matches one backslash character</p>
            </td>
        </tr>
        </colgroup>
    </tbody>
</table>
<a name="pythonian-CHP-9-SECT-7.2"></a></p>
<img src ="http://www.blogjava.net/fhtdy2004/aggbug/292232.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-22 23:48 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292232.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>t.interrupt(),t.isInterrupted(),Thread.interrupted()</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292181.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Sat, 22 Aug 2009 03:07:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292181.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/292181.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292181.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/292181.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/292181.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在学校的论坛Java版发现很多问关于这样的问题，比如这几个方法有什么区别，想看t.interrupt()方法后线程的中断状态；如何终止一个线程其实之前已经大部分提及到。现总结一下，然后加上例子，毕竟例子容易理解http://www.blogjava.net/fhtdy2004/archive/2009/06/08/280728.html中有关interrupt()的解释已经很清楚了...&nbsp;&nbsp;<a href='http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292181.html'>阅读全文</a><img src ="http://www.blogjava.net/fhtdy2004/aggbug/292181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-22 11:07 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python学习笔记一</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292168.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Fri, 21 Aug 2009 16:02:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292168.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/292168.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/292168.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/292168.html</trackback:ping><description><![CDATA[<p>发现很多公司要求掌握一门脚本语言，一直也想搞搞这个，看C++，Linux C编程也只是为了对系统更加的了解，唉，我的工作定位好像一直都不怎么明确，是要搞个自己最擅长的了，以后有时间再搞linuxC，找工作第一位。。。工作基本定位在 Java+python，大部分公司也不会要求一个人既做Java也做C++。再说这语言也是大同小异，关键还是编程思想<br />
<br />
<br />
d = {"server":"mpilgrim", "database":"master"}</p>
<p>li = ["a", "b", "mpilgrim", "z", "example"]</p>
<p><br />
Tuple 是不可变的 list。一旦创建了一个 tuple，就不能以任何方式改变它<br />
&nbsp;t = ("a", "b", "mpilgrim", "z", "example") </p>
<p><br />
连接 list 与分割字符串<br />
&gt;&gt;&gt; li = ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']<br />
&gt;&gt;&gt; s = ";".join(li)<br />
&gt;&gt;&gt; s<br />
'server=mpilgrim;uid=sa;database=master;pwd=secret'<br />
&gt;&gt;&gt; s.split(";")&nbsp;&nbsp;&nbsp; <br />
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']<br />
&gt;&gt;&gt; s.split(";", 1) <br />
['server=mpilgrim', 'uid=sa;database=master;pwd=secret']</p>
<p>&nbsp;</p>
<p><br />
使用 type、str、dir 和其它内置函数</p>
<p>4.3.2. str 函数 <br />
str 将数据强制转换为字符串。每种数据类型都可以强制转换为字符串。 </p>
<p>例 4.6. str 介绍 <br />
&gt;&gt;&gt; str(1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
'1'<br />
&gt;&gt;&gt; horsemen = ['war', 'pestilence', 'famine']<br />
&gt;&gt;&gt; horsemen<br />
['war', 'pestilence', 'famine']<br />
&gt;&gt;&gt; horsemen.append('Powerbuilder')<br />
&gt;&gt;&gt; str(horsemen)&nbsp;&nbsp; <br />
"['war', 'pestilence', 'famine', 'Powerbuilder']"<br />
&gt;&gt;&gt; str(odbchelper) <br />
"&lt;module 'odbchelper' from 'c:\\docbook\\dip\\py\\odbchelper.py'&gt;"<br />
&gt;&gt;&gt; str(None)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
'None'&nbsp; 对于简单的数据类型比如整型，你可以预料到 str 的正常工作，因为几乎每种语言都有一个</p>
<p>将整型转化为字符串的函数。&nbsp; <br />
&nbsp; 然而 str 可以作用于任何数据类型的任何对象。这里它作用于一个零碎构建的列表。&nbsp; <br />
&nbsp; str 还允许作用于模块。注意模块的字符串形式表示包含了模块在磁盘上的路径名，所以你的显示</p>
<p>结果将会有所不同。&nbsp; <br />
&nbsp; str 的一个细小但重要的行为是它可以作用于 None，None 是 Python 的 null 值。这个调用返回字符</p>
<p>串 'None'。你将会使用这一点来改进你的 info 函数，这一点你很快就会看到。&nbsp; </p>
<p><br />
dir 函数返回任意对象的属性和方法列表，包括模块对象、函数对象、字符串对象、列表对象、字</p>
<p>典对象 &#8230;&#8230; 相当多的东西。 </p>
<p>例 4.7. dir 介绍 <br />
&gt;&gt;&gt; li = []<br />
&gt;&gt;&gt; dir(li)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
['append', 'count', 'extend', 'index', 'insert',<br />
'pop', 'remove', 'reverse', 'sort']<br />
&gt;&gt;&gt; d = {}<br />
&gt;&gt;&gt; dir(d)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']<br />
&gt;&gt;&gt; import odbchelper<br />
&gt;&gt;&gt; dir(odbchelper)&nbsp;&nbsp; <br />
['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']</p>
<p>&nbsp;</p>
<p>最后是 callable 函数，它接收任何对象作为参数，如果参数对象是可调用的，返回 True；否则返回 </p>
<p>False。可调用对象包括函数、类方法，甚至类自身 (下一章将更多的关注类)。 </p>
<p>例 4.8. callable 介绍 <br />
&gt;&gt;&gt; import string<br />
&gt;&gt;&gt; string.punctuation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
'!"#$%&amp;\'()*+,-./:;&lt;=&gt;?@[\\]^_`{|}~'<br />
&gt;&gt;&gt; string.join&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;function join at 00C55A7C&gt;<br />
&gt;&gt;&gt; callable(string.punctuation) <br />
False<br />
&gt;&gt;&gt; callable(string.join)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
True</p>
<p><br />
你已经知道 Python 函数是对象。你不知道的是，使用 getattr 函数，可以得到一个直到运行时才知</p>
<p>道名称的函数的引用。 </p>
<p>例 4.10. getattr 介绍 <br />
&gt;&gt;&gt; li = ["Larry", "Curly"]<br />
&gt;&gt;&gt; li.pop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;built-in method pop of list object at 010DF884&gt;<br />
&gt;&gt;&gt; getattr(li, "pop")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;built-in method pop of list object at 010DF884&gt;<br />
&gt;&gt;&gt; getattr(li, "append")("Moe") <br />
&gt;&gt;&gt; li<br />
["Larry", "Curly", "Moe"]<br />
&gt;&gt;&gt; getattr({}, "clear")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;built-in method clear of dictionary object at 00F113D4&gt;<br />
&gt;&gt;&gt; getattr((), "pop")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
Traceback (innermost last):<br />
&nbsp; File "&lt;interactive input&gt;", line 1, in ?<br />
AttributeError: 'tuple' object has no attribute 'pop'</p>
<p>&nbsp;</p>
<p>4.4.1. 用于模块的 getattr<br />
getattr 不仅仅适用于内置数据类型，也可作用于模块。 </p>
<p>例 4.11. apihelper.py 中的 getattr 函数 <br />
&gt;&gt;&gt; import odbchelper<br />
&gt;&gt;&gt; odbchelper.buildConnectionString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;function buildConnectionString at 00D18DD4&gt;<br />
&gt;&gt;&gt; getattr(odbchelper, "buildConnectionString") <br />
&lt;function buildConnectionString at 00D18DD4&gt;<br />
&gt;&gt;&gt; object = odbchelper<br />
&gt;&gt;&gt; method = "buildConnectionString"<br />
&gt;&gt;&gt; getattr(object, method)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;function buildConnectionString at 00D18DD4&gt;<br />
&gt;&gt;&gt; type(getattr(object, method))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;type 'function'&gt;<br />
&gt;&gt;&gt; import types<br />
&gt;&gt;&gt; type(getattr(object, method)) == types.FunctionType<br />
True<br />
&gt;&gt;&gt; callable(getattr(object, method))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
True</p>
<p><br />
使用 getattr，你能够获得同一函数的同一引用。通常，getattr(object, "attribute") 等价于 </p>
<p>object.attribute。如果 object 是一个模块的话，那么 attribute 可能是定义在模块中的任何东西：函数</p>
<p>、类或者全局变量。</p>
<p><br />
就是相当于函数的指针<br />
例 4.12. 使用getattr 创建分发者 </p>
<p>import statsout</p>
<p>def output(data, format="text"):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; output_function = getattr(statsout, "output_%s" % format) <br />
&nbsp;&nbsp;&nbsp; return output_function(data)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; output 函数接收一个必备参数 data，和一个可选参数 format。如果没有指定 format 参数，其缺省</p>
<p>值是 text 并完成普通文本输出函数的调用。&nbsp; <br />
&nbsp; 你可以连接 format 参数值和 "output_" 来创建一个函数名称作为参数值，然后从 statsout 模块中取</p>
<p>得该函数。这种方式允许今后很容易地扩展程序以支持其它的输出格式，而且无需修改分发函数。</p>
<p>所要做的仅仅是向 statsout 中添加一个函数，比如 output_pdf，之后只要将 &#8220;pdf&#8221; 作为 format 的参</p>
<p>数值传递给 output 函数即可。&nbsp; <br />
&nbsp; 现在你可以简单地调用输出函数，就像调用其它函数一样。output_function 变量是指向 statsout 模</p>
<p>块中相应函数的引用。&nbsp; </p>
<p>你是否发现前面示例的一个 Bug？即字符串和函数之间的松耦合，而且没有错误检查。如果用户传</p>
<p>入一个格式参数，但是在 statsout 中没有定义相应的格式输出函数，会发生什么呢？还好，getattr </p>
<p>会返回 None，它会取代一个有效函数并被赋值给 output_function，然后下一行调用函数的语句将会</p>
<p>失败并抛出一个异常。这种方式不好。 </p>
<p>值得庆幸的是，getattr 能够使用可选的第三个参数，一个缺省返回值。</p>
<p>&nbsp;</p>
<p>[mapping-expression for element in source-list if filter-expression]</p>
<p>&gt;&gt;&gt; li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]<br />
&gt;&gt;&gt; [elem for elem in li if len(elem) &gt; 1]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
['mpilgrim', 'foo']<br />
&gt;&gt;&gt; [elem for elem in li if elem != "b"]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
['a', 'mpilgrim', 'foo', 'c', 'd', 'd']<br />
&gt;&gt;&gt; [elem for elem in li if li.count(elem) == 1] <br />
['a', 'mpilgrim', 'foo', 'c']</p>
<p><br />
使用 and 时，在布尔环境中从左到右演算表达式的值。0、''、[]、()、{}、None 在布尔环境中为假；</p>
<p>其它任何东西都为真。还好，几乎是所有东西。默认情况下，布尔环境中的类实例为真，但是你可</p>
<p>以在类中定义特定的方法使得类实例的演算值为假。</p>
<p><br />
4.6.1. 使用 and-or 技巧 <br />
例 4.17. and-or 技巧介绍 <br />
&gt;&gt;&gt; a = "first"<br />
&gt;&gt;&gt; b = "second"<br />
&gt;&gt;&gt; 1 and a or b <br />
'first'<br />
&gt;&gt;&gt; 0 and a or b <br />
'second'<br />
&nbsp; 这个语法看起来类似于 C 语言中的 bool ? a : b 表达式。整个表达式从左到右进行演算，所以先进</p>
<p>行 and 表达式的演算。1 and 'first' 演算值为 'first'，然后 'first' or 'second' 的演算值为 'first'。&nbsp; <br />
&nbsp; 0 and 'first' 演算值为 False，然后 0 or 'second' 演算值为 'second'。&nbsp; </p>
<p>然而，由于这种 Python 表达式单单只是进行布尔逻辑运算，并不是语言的特定构成，这是 and-or </p>
<p>技巧和 C 语言中的 bool ? a : b 语法非常重要的不同。如果 a 为假，表达式就不会按你期望的那样</p>
<p>工作了。(你能知道我被这个问题折腾过吗？不止一次？) </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
Python 支持一种有趣的语法，它允许你快速定义单行的最小函数。这些叫做 lambda 的函数，是从 </p>
<p>Lisp 借用来的，可以用在任何需要函数的地方。<br />
例 4.20. lambda 函数介绍 <br />
&gt;&gt;&gt; def f(x):<br />
...&nbsp;&nbsp;&nbsp;&nbsp; return x*2<br />
...&nbsp;&nbsp;&nbsp;&nbsp; <br />
&gt;&gt;&gt; f(3)<br />
6<br />
&gt;&gt;&gt; g = lambda x: x*2&nbsp; <br />
&gt;&gt;&gt; g(3)<br />
6<br />
&gt;&gt;&gt; (lambda x: x*2)(3) <br />
6</p>
<p>总的来说，lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值。lambda </p>
<p>函数不能包含命令，包含的表达式不能超过一个。不要试图向 lambda 函数中塞入太多的东西；如</p>
<p>果你需要更复杂的东西，应该定义一个普通函数，然后想让它多长就多长。 </p>
<p>&nbsp;</p>
<p><br />
例 4.25. 打印列表<br />
&gt;&gt;&gt; li = ['a', 'b', 'c']<br />
&gt;&gt;&gt; print "\n".join(li) <br />
a<br />
b<br />
c&nbsp; 在你处理列表时，这确实是一个有用的调试技巧。在 Python 中，你会十分频繁地操作列表。&nbsp; </p>
<p>&nbsp;</p>
<p>在 2.2.1 版本之前，Python 没有单独的布尔数据类型。为了弥补这个缺陷，Python 在布尔环境 (如 if </p>
<p>语句) 中几乎接受所有东西，遵循下面的规则： <br />
0 为 false; 其它所有数值皆为 true。 <br />
空串 ("") 为 false; 其它所有字符串皆为 true。 <br />
空 list ([]) 为 false; 其它所有 list 皆为 true。 <br />
空 tuple (()) 为 false; 其它所有 tuple 皆为 true。 <br />
空 dictionary ({}) 为 false; 其它所有 dictionary 皆为 true。 </p>
<p>&nbsp;</p>
<p><br />
下面是 from module import 的基本语法： </p>
<p><br />
from UserDict import UserDict<br />
它与你所熟知的 import module 语法很相似，但是有一个重要的区别：UserDict 被直接导入到局部</p>
<p>名字空间去了，所以它可以直接使用，而不需要加上模块名的限定。你可以导入独立的项或使用 </p>
<p>from module import * 来导入所有东西。 </p>
<p>Python 中的 from module import * 像 Java 中的 import module.* ；Python 中的 import module 像 Java </p>
<p>中的 import module </p>
<p>什么时候你应该使用 from module import？ </p>
<p>如果你要经常访问模块的属性和方法，且不想一遍又一遍地敲入模块名，使用 from module import</p>
<p>。 <br />
如果你想要有选择地导入某些属性和方法，而不想要其它的，使用 from module import。 <br />
如果模块包含的属性和方法与你的某个模块同名，你必须使用 import module 来避免名字冲突。</p>
<p>尽量少用 from module import * ，因为判定一个特殊的函数或属性是从哪来的有些困难，并且会造</p>
<p>成调试和重构都更困难。</p>
<p><br />
from UserDict import UserDict</p>
<p>class FileInfo(UserDict): <br />
在 Python 中，类的基类只是简单地列在类名后面的小括号里。不像在 Java 中有一个特殊的 </p>
<p>extends 关键字。&nbsp; </p>
<p>Python 支持多重继承。在类名后面的小括号中，你可以列出许多你想要的类名，以逗号分隔。 </p>
<p><br />
class FileInfo(UserDict):<br />
&nbsp;&nbsp;&nbsp; "store file metadata"<br />
&nbsp;&nbsp;&nbsp; def __init__(self, filename=None):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserDict.__init__(self)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self["name"] = filename&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一些伪面向对象语言，像 Powerbuilder 有一种&#8220;扩展&#8221;构造函数和其它事件的</p>
<p><span style="color: red"><strong>概念，即父类的方法在子类的方法执行前被自动调用。Python 不是这样，你必须显示地调用在父类中的合适方法。&nbsp; <br />
&nbsp; 我告诉过你，这个类像字典一样工作，那么这里就是第一个印象。我们将参数 filename 赋值给对象 name 关键字，作为它的值。&nbsp;&nbsp;注意 __init__ 方法从不返回一个值。&nbsp; </strong></span><br />
Java中是自动调用默认的无参的父类的构造函数</p>
<p>&nbsp;</p>
<p><br />
例 5.9. 定义 UserDict 类 </p>
<p>class UserDict:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; def __init__(self, dict=None):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red"><strong>&nbsp; self.data = {}&nbsp; &#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;定义类的实例变量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</strong></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if dict is not None: self.update(dict)&nbsp; <br />
&nbsp; 注意 UserDict 是一个基类，不是从任何其他类继承而来。&nbsp; <br />
&nbsp; 这就是我们在 FileInfo 类中进行了覆盖的 __init__ 方法。注意这个父类的参数列表与子类不同。很</p>
<p>好，每个子类可以拥有自已的参数集，只要使用正确的参数调用父类就可以了。这里父类有一个定</p>
<p>义初始值的方法 (通过在 dict 参数中传入一个字典)，这一方法我们的 FileInfo 没有用上。<br />
</p>
<p><br />
<span style="color: red"><strong>&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;与Java的不同&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;<br />
与Java的不同，<br />
1，Python中类的类属性是是在类的后面直接定义的<br />
2，而实例变量是在在__init__方法中直接定义的使用如下方式self.instancevariable=***定义,<br />
3，然后Python中实例方法都要显示的加上self（相当于Java的this)参数，方法中引用实例变<span style="color: red">量时也要通过self来引用</span></strong></span></p>
<p>Python 支持数据属性 (在 Java 叫做 &#8220;实例变量&#8221;，在 C++ 中叫 &#8220;数据成员&#8221;)，它是由某个特定的类实</p>
<p>例所拥有的数据。在本例中，每个 UserDict 实例将拥有一个 data 数据属性。要从类外的代码引用</p>
<p>这个属性，需要用实例的名字限定它，instance.data，限定的方法与你用模块的名字来限定函数一</p>
<p>样。要在类的内部引用一个数据属性，我们使用 self 作为限定符。习惯上，所有的数据属性都在 </p>
<p>__init__ 方法中初始化为有意义的值。然而，这并不是必须的，因为数据属性，像局部变量一样，</p>
<p>当你首次赋给它值的时候突然产生。&nbsp; <br />
&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;与Java的不同&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;</p>
<p>Java 支持通过参数列表的重载，也就是 一个类可以有同名的多个方法，但这些方法或者是参数个</p>
<p>数不同，或者是参数的类型不同。<br />
Python 两种都不支持，总之是没有任何形式的函数重载。一个 __init__ 方法就是一个 __init__ 方法</p>
<p>，不管它有什么样的参数。每个类只能有一个 __init__ 方法，并且如果一个子类拥有一个 __init__ </p>
<p>方法，它总是 覆盖父类的 __init__ 方法，甚至子类可以用不同的参数列表来定义它。 </p>
<p><span style="color: red"><strong>想想为什么不支持方法重载，是因为Python的参数可以定义默认实参，有缺省值</strong></span><br />
&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;<br />
应该总是在 __init__ 方法中给一个实例的所有数据属性赋予一个初始值。这样做将会节省你在后面</p>
<p>调试的时间，不必为捕捉因使用未初始化 (也就是不存在) 的属性而导致的 AttributeError 异常费时费</p>
<p>力。 <br />
<span style="color: red">class MP3FileInfo(FileInfo):<br />
mp3file.__class__&nbsp; is fileinfo.MP3FileInfo true<br />
mp3file.__class__&nbsp; is fileinfo.FileInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; false<br />
isinstance(mp3file,fileinfo.MP3FileInfo)&nbsp; true<br />
isinstance(mp3file,fileinfo.FileInfo)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true</span></p>
<p><span style="color: red">li=[1,2,3]<br />
li2[1,2,3]<br />
li==li2 true&nbsp;&nbsp; 相当于Java的equals()<br />
li is li2 false 相当于Java的==</span></p>
<p><br />
5.7. 高级专用类方法 <br />
除了 __getitem__ 和 __setitem__ 之外 Python 还有更多的专用函数。某些可以让你模拟出你甚至可</p>
<p>能不知道的功能。 </p>
<p>下面的例子将展示 UserDict 一些其他专用方法。 </p>
<p>例 5.16. UserDict 中更多的专用方法 <br />
&nbsp;&nbsp;&nbsp; def __repr__(self): return repr(self.data)&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; def __cmp__(self, dict):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if isinstance(dict, UserDict):&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return cmp(self.data, dict.data)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return cmp(self.data, dict)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; def __len__(self): return len(self.data)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; def __delitem__(self, key): del self.data[key]&nbsp;&nbsp; __repr__ 是一个专用的方法，在当调用 repr</p>
<p>(instance) 时被调用。repr 函数是一个内置函数，它返回一个对象的字符串表示。它可以用在任何</p>
<p>对象上，不仅仅是类的实例。你已经对 repr 相当熟悉了，尽管你不知道它。在交互式窗口中，当你</p>
<p>只敲入一个变量名，接着按ENTER，Python 使用 repr 来显示变量的值。自已用一些数据来创建一</p>
<p>个字典 d ，然后用 print repr(d) 来看一看吧。&nbsp; <br />
&nbsp; __cmp__ 在比较类实例时被调用。通常，你可以通过使用 == 比较任意两个 Python 对象，不只是</p>
<p>类实例。有一些规则，定义了何时内置数据类型被认为是相等的，例如，字典在有着全部相同的关</p>
<p>键字和值时是相等的。对于类实例，你可以定义 __cmp__ 方法，自已编写比较逻辑，然后你可以</p>
<p>使用 == 来比较你的类，Python 将会替你调用你的 __cmp__ 专用方法。&nbsp; <br />
&nbsp; __len__ 在调用 len(instance) 时被调用。len 是一个内置函数，可以返回一个对象的长度。它可以</p>
<p>用于任何被认为理应有长度的对象。字符串的 len 是它的字符个数；字典的 len 是它的关键字的个</p>
<p>数；列表或序列的 len 是元素的个数。对于类实例，定义 __len__ 方法，接着自已编写长度的计算</p>
<p>，然后调用 len(instance)，Python 将替你调用你的 __len__ 专用方法。&nbsp; <br />
&nbsp; __delitem__ 在调用 del instance[key] 时调用 ，你可能记得它作为从字典中删除单个元素的方法。</p>
<p>当你在类实例中使用 del 时，Python 替你调用 __delitem__ 专用方法。&nbsp; </p>
<p>&nbsp;<br />
在 Java 中，通过使用 str1 == str2 可以确定两个字符串变量是否指向同一块物理内存位置。这叫做</p>
<p>对象同一性，在 Python 中写为 str1 is str2。在 Java 中要比较两个字符串值，你要使用 str1.equals</p>
<p>(str2)；在 Python 中，你要使用 str1 == str2。某些 Java 程序员，他们已经被教授得认为，正是因为</p>
<p>在 Java 中 == 是通过同一性而不是值进行比较，所以世界才会更美好。这些人要接受 Python 的这</p>
<p>个&#8220;严重缺失&#8221;可能要花些时间。&nbsp; </p>
<p><br />
ord("a") 97<br />
ord("A") 65</p>
<p>&nbsp;</p>
<p>5.8. 类属性介绍 <br />
你已经知道了数据属性，它们是被一个特定的类实例所拥有的变量。Python 也支持类属性，它们是</p>
<p>由类本身所拥有的。 </p>
<p>例 5.17. 类属性介绍</p>
<p>class MP3FileInfo(FileInfo):<br />
&nbsp;&nbsp;&nbsp; "store ID3v1.0 MP3 tags"<br />
&nbsp;&nbsp;&nbsp; tagDataMap = {"title"&nbsp;&nbsp; : (&nbsp; 3,&nbsp; 33, stripnulls),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "artist"&nbsp; : ( 33,&nbsp; 63, stripnulls),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "album"&nbsp;&nbsp; : ( 63,&nbsp; 93, stripnulls),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "year"&nbsp;&nbsp;&nbsp; : ( 93,&nbsp; 97, stripnulls),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "comment" : ( 97, 126, stripnulls),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "genre"&nbsp;&nbsp; : (127, 128, ord)}</p>
<p><br />
例 5.18. 修改类属性,Java中的静态变量<br />
&gt;&gt;&gt; class counter:<br />
...&nbsp;&nbsp;&nbsp;&nbsp; count = 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
...&nbsp;&nbsp;&nbsp;&nbsp; def __init__(self):<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red">&nbsp;self.__class__.count += 1 #一定得用self.__class__来引用，才是类变量，<span style="color: red">假如用self.count则定义的是实例变量,或者用<br />
</span></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red">&nbsp; Counter.count +=1<br />
</span>...&nbsp;&nbsp;&nbsp;&nbsp; <br />
上述代码记录创建的对象的个数</p>
<p>&nbsp;</p>
<p>5.9. 私有函数 <br />
与大多数语言一样，Python 也有私有的概念： </p>
<p>私有函数不可以从它们的模块外面被调用 <br />
私有类方法不能够从它们的类外面被调用 <br />
私有属性不能够从它们的类外面被访问 <br />
与大多数的语言不同，一个 Python 函数，方法，或属性是私有还是公有，完全取决于它的名字。 </p>
<p>如果一个 Python 函数，类方法，或属性的名字以两个下划线开始 (但不是结束)，它是私有的；其它</p>
<p>所有的都是公有的。 Python 没有类方法保护 的概念 (只能用于它们自已的类和子类中)。类方法或</p>
<p>者是私有 (只能在它们自已的类中使用) 或者是公有 (任何地方都可使用)。 </p>
<p>在 MP3FileInfo 中，有两个方法：__parse 和 __setitem__。正如我们已经讨论过的，__setitem__ </p>
<p>是一个专有方法；通常，你不直接调用它，而是通过在一个类上使用字典语法来调用，但它是公有</p>
<p>的，并且如果有一个真正好的理由，你可以直接调用它 (甚至从 fileinfo 模块的外面)。然而，</p>
<p>__parse 是私有的，因为在它的名字前面有两个下划线。 </p>
<p>&nbsp;<br />
在 Python 中，所有的专用方法 (像 __setitem__) 和内置属性 (像 __doc__) 遵守一个标准的命名习惯</p>
<p>：开始和结束都有两个下划线。不要对你自已的方法和属性用这种方法命名；到最后，它只会把你 (或其它人) 搞乱。 <br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #008000">#</span><span style="color: #008000">!/usr/bin/env&nbsp;python</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />#</span><span style="color: #008000">coding=utf-8</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;os<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;sys<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">from</span><span style="color: #000000">&nbsp;UserDict&nbsp;</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;UserDict<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">def</span><span style="color: #000000">&nbsp;stripnulls(data):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">strip&nbsp;whitespace&nbsp;and&nbsp;null</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;data.replace(</span><span style="color: #800000">"</span><span style="color: #800000">\00</span><span style="color: #800000">"</span><span style="color: #000000">,</span><span style="color: #800000">""</span><span style="color: #000000">).strip()<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;FileInfo(UserDict):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">store&nbsp;file&nbsp;metadata</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">def</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">__init__</span><span style="color: #000000">(self,filename</span><span style="color: #000000">=</span><span style="color: #000000">None):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserDict.</span><span style="color: #800080">__init__</span><span style="color: #000000">(self)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">#</span><span style="color: #008000">will&nbsp;trigger&nbsp;the&nbsp;__setitem__&nbsp;method,and&nbsp;this&nbsp;method&nbsp;be&nbsp;override&nbsp;in&nbsp;the&nbsp;sub&nbsp;class</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[</span><span style="color: #800000">"</span><span style="color: #800000">name</span><span style="color: #800000">"</span><span style="color: #000000">]</span><span style="color: #000000">=</span><span style="color: #000000">filename<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;MP3FileInfo(FileInfo):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">store&nbsp;ID3v1.0&nbsp;MP3&nbsp;tags</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;tagDataMap</span><span style="color: #000000">=</span><span style="color: #000000">{</span><span style="color: #800000">"</span><span style="color: #800000">title</span><span style="color: #800000">"</span><span style="color: #000000">:(</span><span style="color: #000000">3</span><span style="color: #000000">,</span><span style="color: #000000">33</span><span style="color: #000000">,stripnulls),<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">artist</span><span style="color: #800000">"</span><span style="color: #000000">:(</span><span style="color: #000000">33</span><span style="color: #000000">,</span><span style="color: #000000">63</span><span style="color: #000000">,stripnulls),<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">album</span><span style="color: #800000">"</span><span style="color: #000000">&nbsp;:(</span><span style="color: #000000">63</span><span style="color: #000000">,</span><span style="color: #000000">93</span><span style="color: #000000">,stripnulls),<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">year</span><span style="color: #800000">"</span><span style="color: #000000">&nbsp;&nbsp;:(</span><span style="color: #000000">93</span><span style="color: #000000">,</span><span style="color: #000000">97</span><span style="color: #000000">,stripnulls),<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">comment</span><span style="color: #800000">"</span><span style="color: #000000">:(</span><span style="color: #000000">97</span><span style="color: #000000">,</span><span style="color: #000000">126</span><span style="color: #000000">,stripnulls),<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">genre</span><span style="color: #800000">"</span><span style="color: #000000">&nbsp;:(</span><span style="color: #000000">127</span><span style="color: #000000">,</span><span style="color: #000000">128</span><span style="color: #000000">,ord)}<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">def</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">__parse</span><span style="color: #000000">(self,filename):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">parse&nbsp;ID3v1.0&nbsp;tags&nbsp;from&nbsp;Mp3&nbsp;file</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.clear()<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fsock&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;open(filename,</span><span style="color: #800000">"</span><span style="color: #800000">rb</span><span style="color: #800000">"</span><span style="color: #000000">,0)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fsock.seek(</span><span style="color: #000000">-</span><span style="color: #000000">128</span><span style="color: #000000">,</span><span style="color: #000000">2</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tagdata&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;fsock.read(</span><span style="color: #000000">128</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">finally</span><span style="color: #000000">:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fsock.close()<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;tagdata[:</span><span style="color: #000000">3</span><span style="color: #000000">]</span><span style="color: #000000">==</span><span style="color: #800000">"</span><span style="color: #800000">TAG</span><span style="color: #800000">"</span><span style="color: #000000">:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;tag,(start,end,parseFunc)&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;self.tagDataMap.items():<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self[tag]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;parseFunc(tagdata[start:end])<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">except</span><span style="color: #000000">&nbsp;IOError:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">pass</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">def</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">__setitem__</span><span style="color: #000000">(self,key,item):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;key&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">name</span><span style="color: #800000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">and</span><span style="color: #000000">&nbsp;item:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.</span><span style="color: #800080">__parse</span><span style="color: #000000">(item)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileInfo.</span><span style="color: #800080">__setitem__</span><span style="color: #000000">(self,key,item)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">def</span><span style="color: #000000">&nbsp;listDirectory(directory,fileExtList):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">get&nbsp;list&nbsp;of&nbsp;file&nbsp;info&nbsp;object&nbsp;for&nbsp;files&nbsp;of&nbsp;particular</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;fileList&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;[os.path.normcase(f)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;f&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;os.listdir(directory)]<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;fileList&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;[os.path.join(directory,f)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;f&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;fileList&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;os.path.splitext(f)[</span><span style="color: #000000">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;fileExtList]<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">def</span><span style="color: #000000">&nbsp;getFileInfoClass(filename,module</span><span style="color: #000000">=</span><span style="color: #000000">sys.modules[FileInfo.</span><span style="color: #800080">__module__</span><span style="color: #000000">]):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">get&nbsp;file&nbsp;into&nbsp;class&nbsp;from&nbsp;filename&nbsp;extension</span><span style="color: #800000">"</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subclass&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">%sFileInfo</span><span style="color: #800000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">&nbsp;os.path.splitext(filename)[</span><span style="color: #000000">1</span><span style="color: #000000">].upper()[</span><span style="color: #000000">1</span><span style="color: #000000">:]<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;hasattr(module,subclass)&nbsp;</span><span style="color: #0000ff">and</span><span style="color: #000000">&nbsp;getattr(module,subclass)&nbsp;</span><span style="color: #0000ff">or</span><span style="color: #000000">&nbsp;FileInfo<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;[getFileInfoClass(f)(f)&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;f&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;fileList]<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;</span><span style="color: #800080">__name__</span><span style="color: #000000">==</span><span style="color: #800000">"</span><span style="color: #800000">__main__</span><span style="color: #800000">"</span><span style="color: #000000">:<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;info&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;listDirectory(</span><span style="color: #800000">"</span><span style="color: #800000">G:\\test</span><span style="color: #800000">"</span><span style="color: #000000">,[</span><span style="color: #800000">"</span><span style="color: #800000">.mp3</span><span style="color: #800000">"</span><span style="color: #000000">]):<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">print</span><span style="color: #000000">&nbsp;</span><span style="color: #800000">"</span><span style="color: #800000">\n</span><span style="color: #800000">"</span><span style="color: #000000">.join([</span><span style="color: #800000">"</span><span style="color: #800000">%s=%s</span><span style="color: #800000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">&nbsp;(k,v)&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(k,v)&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;info.items()])<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">print</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span></div>
<img src ="http://www.blogjava.net/fhtdy2004/aggbug/292168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-22 00:02 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/22/292168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>API转换的问题的解决</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/16/291377.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Sun, 16 Aug 2009 11:30:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/16/291377.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/291377.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/16/291377.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/291377.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/291377.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 有了前几篇关于BCEL的使用，现在API转换的问题其实很简单了实际API转换要做的比这个例子要复杂些，涉及到包名，类名，方法名称等的变化。把常量池变化搞清楚就够了假如这是APIa中的一个类实际只提供APIa的jar包，不提供源代码package&nbsp;one.api;public&nbsp;class&nbsp;MyAPITest&nbsp;{&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/fhtdy2004/archive/2009/08/16/291377.html'>阅读全文</a><img src ="http://www.blogjava.net/fhtdy2004/aggbug/291377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-16 19:30 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/16/291377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 BCEL 设计字节码（三）直接在方法的调用处添加方法</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291097.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Thu, 13 Aug 2009 15:10:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291097.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/291097.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291097.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/291097.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/291097.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这个最接近之前提出的API转换问题这个需要扫描源代码找到此类的方法调用处，然后在方法调用处的前后添加指令即将代码转换成如下形式：public&nbsp;class&nbsp;StringBuilder{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;buildString(int&nbsp;length)&nbsp;{...&nbsp;&nbsp;<a href='http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291097.html'>阅读全文</a><img src ="http://www.blogjava.net/fhtdy2004/aggbug/291097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-13 23:10 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 BCEL 设计字节码（二）直接在原方法上加指令</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291095.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Thu, 13 Aug 2009 14:53:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291095.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/291095.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291095.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/291095.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/291095.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 前一个是直接生成了一个一个方法对原方法进行调用，现在直接在原方法上进行修改即将public&nbsp;class&nbsp;StringBuilder{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;buildString(int&nbsp;length)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291095.html'>阅读全文</a><img src ="http://www.blogjava.net/fhtdy2004/aggbug/291095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-13 22:53 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】用 BCEL 设计字节码</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291025.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Thu, 13 Aug 2009 07:58:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291025.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/291025.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291025.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/291025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/291025.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 查到一篇使用BCEL了,Java 编程的动态性，第 7 部分: 用 BCEL 设计字节码，网址是http://www-128.ibm.com/developerworks/cn/java/j-dyn0414/字节码处理的工具也挺多，什么时候再看看asmimport&nbsp;java.io.FileOutputStream;import&nbsp;org.apache.bcel...&nbsp;&nbsp;<a href='http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291025.html'>阅读全文</a><img src ="http://www.blogjava.net/fhtdy2004/aggbug/291025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-13 15:58 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/13/291025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>API转换的问题的提出</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290784.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Wed, 12 Aug 2009 04:16:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290784.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/290784.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/290784.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/290784.html</trackback:ping><description><![CDATA[<p>假如现有两个API，AIPa，和APIb，两个api定义的类，接口，功能均完全相同，但是有写细微差别，比如说方法的参数类型不同，方法的返回值不同等等。<br />
比如APIa中一个类A的方法为public int add(String a,String b)<br />
比如APIb中的一个类A的方法为 public int&nbsp;add(int a,int b)<br />
<br />
之前有一程序是使用APIa编写的（现在只提供此程序的 class文件，不提供程序的源代码，不允许修改程序的源代码），现在要使这个程序能够在APIb下能够使用？？<br />
<br />
方法一不修改APIb的classes文件，而是修改应用程序的classes文件，将扫描原始应用程序的class文件，将class文件中用到APIa的方法转换成APIb的方法??，这个应该不叫转换，比如在程序中调用a.add("1","2")时，<span style="color: red">在方法调用前将方法栈中的字符串参数转换成数字，使用javassist怎么来做，使用bcel怎么来做？？<br />
</span><br />
方法二不修改应用程序的classes文件，而是修改APIb的classes文件，是将APIb的接口形式转换为APIa的形式，使用javassist重写APIb的方法，对APIb的所有方法进行包装成APIa的方法，然后使用重写的APIb的classes文件来允许程序。这个使用javassist应该比较方便，使用becl?<br />
这个就有点不方便了，如果APIb的类库比较大的话，API间不一致的地方也比较多的话，都需要自己重写，相当于重新包装了这个APIb，需要修改APIb的classes文件，有可能其他程序要用到这个APIb。<br />
<br />
还不太清楚，在仔细想想怎么来做，接下来的工作自己写两套简单的API，然后试验试验。<br />
刚开始想的是使用方法二来做，好像这个不太现实，应该是程序使用到了哪个方法，就对这个方法来进行修改，还是方法一好点。<br />
再好好看看java虚拟机规范。。。<br />
<br />
这个只是一个简单问题的提出，而我实际要转换的程序要比这个复杂，但是基本原理就这了。<br />
tmd，花了一天多把java虚拟机规范看了好几章，我都佩服自己的学习能力，他妈的为什么就找不到实习了？</p>
<img src ="http://www.blogjava.net/fhtdy2004/aggbug/290784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-12 12:16 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java的编程动态性</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290769.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Wed, 12 Aug 2009 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290769.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/290769.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290769.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/290769.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/290769.html</trackback:ping><description><![CDATA[<p>第 1 部分，&#8220; <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0429/" cmimpressionsent="1">类和类装入</a>&#8221;（2003 年 4 月） </p>
<p>第 2 部分，&#8220; <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0603/" cmimpressionsent="1">引入反射</a>&#8221; （2003 年 6 月） </p>
<p>第 3 部分，" <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0715/" cmimpressionsent="1">应用反射</a>" （2003 年 7 月） </p>
<p>第 4 部分，&#8220; <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0916/" cmimpressionsent="1">用 Javassist 进行类转换</a>&#8221; （2003 年 9 月） </p>
<p>第 5 部分，&#8220; <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0203/" cmimpressionsent="1">动态转换类</a>&#8221; （2004 年 2 月） </p>
<p>第 6 部分，&#8220; <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0302/" cmimpressionsent="1">用 Javassit 进行面向方面的更改</a>&#8221;（2004 年 3 月） </p>
<p>第 7 部分，&#8220; <a href="http://www.ibm.com/developerworks/cn/java/j-dyn0414/index.html" cmimpressionsent="1">用 BCEL 设计字节码</a>&#8221; （2004 年 4 月） <br />
<br />
<span style="color: #999999">Java 编程的动态性，第 8 部分: </span>用代码生成取代反射<br />
http://www.ibm.com/developerworks/cn/java/j-dyn0610/<br />
<br />
<br />
<br />
</p>
<img src ="http://www.blogjava.net/fhtdy2004/aggbug/290769.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-12 10:35 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/12/290769.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】Hibernate/Spring/Struts架构使用OpenSessionInView的问题</title><link>http://www.blogjava.net/fhtdy2004/archive/2009/08/09/290400.html</link><dc:creator>Frank_Fang</dc:creator><author>Frank_Fang</author><pubDate>Sat, 08 Aug 2009 16:14:00 GMT</pubDate><guid>http://www.blogjava.net/fhtdy2004/archive/2009/08/09/290400.html</guid><wfw:comment>http://www.blogjava.net/fhtdy2004/comments/290400.html</wfw:comment><comments>http://www.blogjava.net/fhtdy2004/archive/2009/08/09/290400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/fhtdy2004/comments/commentRss/290400.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/fhtdy2004/services/trackbacks/290400.html</trackback:ping><description><![CDATA[<br />
http://www.javaeye.com/topic/15057<br />
<br />
值得研究一下<br />
<img src ="http://www.blogjava.net/fhtdy2004/aggbug/290400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/fhtdy2004/" target="_blank">Frank_Fang</a> 2009-08-09 00:14 <a href="http://www.blogjava.net/fhtdy2004/archive/2009/08/09/290400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>