隨筆-204  評論-149  文章-0  trackbacks-0

          發現很多公司要求掌握一門腳本語言,一直也想搞搞這個,看C++,Linux C編程也只是為了對系統更加的了解,唉,我的工作定位好像一直都不怎么明確,是要搞個自己最擅長的了,以后有時間再搞linuxC,找工作第一位。。。工作基本定位在 Java+python,大部分公司也不會要求一個人既做Java也做C++。再說這語言也是大同小異,關鍵還是編程思想


          d = {"server":"mpilgrim", "database":"master"}

          li = ["a", "b", "mpilgrim", "z", "example"]


          Tuple 是不可變的 list。一旦創建了一個 tuple,就不能以任何方式改變它
           t = ("a", "b", "mpilgrim", "z", "example")


          連接 list 與分割字符串
          >>> li = ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
          >>> s = ";".join(li)
          >>> s
          'server=mpilgrim;uid=sa;database=master;pwd=secret'
          >>> s.split(";")   
          ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
          >>> s.split(";", 1)
          ['server=mpilgrim', 'uid=sa;database=master;pwd=secret']

           


          使用 type、str、dir 和其它內置函數

          4.3.2. str 函數
          str 將數據強制轉換為字符串。每種數據類型都可以強制轉換為字符串。

          例 4.6. str 介紹
          >>> str(1)         
          '1'
          >>> horsemen = ['war', 'pestilence', 'famine']
          >>> horsemen
          ['war', 'pestilence', 'famine']
          >>> horsemen.append('Powerbuilder')
          >>> str(horsemen)  
          "['war', 'pestilence', 'famine', 'Powerbuilder']"
          >>> str(odbchelper)
          "<module 'odbchelper' from 'c:\\docbook\\dip\\py\\odbchelper.py'>"
          >>> str(None)      
          'None'  對于簡單的數據類型比如整型,你可以預料到 str 的正常工作,因為幾乎每種語言都有一個

          將整型轉化為字符串的函數。 
            然而 str 可以作用于任何數據類型的任何對象。這里它作用于一個零碎構建的列表。 
            str 還允許作用于模塊。注意模塊的字符串形式表示包含了模塊在磁盤上的路徑名,所以你的顯示

          結果將會有所不同。 
            str 的一個細小但重要的行為是它可以作用于 None,None 是 Python 的 null 值。這個調用返回字符

          串 'None'。你將會使用這一點來改進你的 info 函數,這一點你很快就會看到。 


          dir 函數返回任意對象的屬性和方法列表,包括模塊對象、函數對象、字符串對象、列表對象、字

          典對象 …… 相當多的東西。

          例 4.7. dir 介紹
          >>> li = []
          >>> dir(li)          
          ['append', 'count', 'extend', 'index', 'insert',
          'pop', 'remove', 'reverse', 'sort']
          >>> d = {}
          >>> dir(d)           
          ['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']
          >>> import odbchelper
          >>> dir(odbchelper)  
          ['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']

           

          最后是 callable 函數,它接收任何對象作為參數,如果參數對象是可調用的,返回 True;否則返回

          False。可調用對象包括函數、類方法,甚至類自身 (下一章將更多的關注類)。

          例 4.8. callable 介紹
          >>> import string
          >>> string.punctuation          
          '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
          >>> string.join                 
          <function join at 00C55A7C>
          >>> callable(string.punctuation)
          False
          >>> callable(string.join)       
          True


          你已經知道 Python 函數是對象。你不知道的是,使用 getattr 函數,可以得到一個直到運行時才知

          道名稱的函數的引用。

          例 4.10. getattr 介紹
          >>> li = ["Larry", "Curly"]
          >>> li.pop                      
          <built-in method pop of list object at 010DF884>
          >>> getattr(li, "pop")          
          <built-in method pop of list object at 010DF884>
          >>> getattr(li, "append")("Moe")
          >>> li
          ["Larry", "Curly", "Moe"]
          >>> getattr({}, "clear")        
          <built-in method clear of dictionary object at 00F113D4>
          >>> getattr((), "pop")          
          Traceback (innermost last):
            File "<interactive input>", line 1, in ?
          AttributeError: 'tuple' object has no attribute 'pop'

           

          4.4.1. 用于模塊的 getattr
          getattr 不僅僅適用于內置數據類型,也可作用于模塊。

          例 4.11. apihelper.py 中的 getattr 函數
          >>> import odbchelper
          >>> odbchelper.buildConnectionString            
          <function buildConnectionString at 00D18DD4>
          >>> getattr(odbchelper, "buildConnectionString")
          <function buildConnectionString at 00D18DD4>
          >>> object = odbchelper
          >>> method = "buildConnectionString"
          >>> getattr(object, method)                     
          <function buildConnectionString at 00D18DD4>
          >>> type(getattr(object, method))               
          <type 'function'>
          >>> import types
          >>> type(getattr(object, method)) == types.FunctionType
          True
          >>> callable(getattr(object, method))           
          True


          使用 getattr,你能夠獲得同一函數的同一引用。通常,getattr(object, "attribute") 等價于

          object.attribute。如果 object 是一個模塊的話,那么 attribute 可能是定義在模塊中的任何東西:函數

          、類或者全局變量。


          就是相當于函數的指針
          例 4.12. 使用getattr 創建分發者

          import statsout

          def output(data, format="text"):                             
              output_function = getattr(statsout, "output_%s" % format)
              return output_function(data)                             
            output 函數接收一個必備參數 data,和一個可選參數 format。如果沒有指定 format 參數,其缺省

          值是 text 并完成普通文本輸出函數的調用。 
            你可以連接 format 參數值和 "output_" 來創建一個函數名稱作為參數值,然后從 statsout 模塊中取

          得該函數。這種方式允許今后很容易地擴展程序以支持其它的輸出格式,而且無需修改分發函數。

          所要做的僅僅是向 statsout 中添加一個函數,比如 output_pdf,之后只要將 “pdf” 作為 format 的參

          數值傳遞給 output 函數即可。 
            現在你可以簡單地調用輸出函數,就像調用其它函數一樣。output_function 變量是指向 statsout 模

          塊中相應函數的引用。 

          你是否發現前面示例的一個 Bug?即字符串和函數之間的松耦合,而且沒有錯誤檢查。如果用戶傳

          入一個格式參數,但是在 statsout 中沒有定義相應的格式輸出函數,會發生什么呢?還好,getattr

          會返回 None,它會取代一個有效函數并被賦值給 output_function,然后下一行調用函數的語句將會

          失敗并拋出一個異常。這種方式不好。

          值得慶幸的是,getattr 能夠使用可選的第三個參數,一個缺省返回值。

           

          [mapping-expression for element in source-list if filter-expression]

          >>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
          >>> [elem for elem in li if len(elem) > 1]      
          ['mpilgrim', 'foo']
          >>> [elem for elem in li if elem != "b"]        
          ['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
          >>> [elem for elem in li if li.count(elem) == 1]
          ['a', 'mpilgrim', 'foo', 'c']


          使用 and 時,在布爾環境中從左到右演算表達式的值。0、''、[]、()、{}、None 在布爾環境中為假;

          其它任何東西都為真。還好,幾乎是所有東西。默認情況下,布爾環境中的類實例為真,但是你可

          以在類中定義特定的方法使得類實例的演算值為假。


          4.6.1. 使用 and-or 技巧
          例 4.17. and-or 技巧介紹
          >>> a = "first"
          >>> b = "second"
          >>> 1 and a or b
          'first'
          >>> 0 and a or b
          'second'
            這個語法看起來類似于 C 語言中的 bool ? a : b 表達式。整個表達式從左到右進行演算,所以先進

          行 and 表達式的演算。1 and 'first' 演算值為 'first',然后 'first' or 'second' 的演算值為 'first'。 
            0 and 'first' 演算值為 False,然后 0 or 'second' 演算值為 'second'。 

          然而,由于這種 Python 表達式單單只是進行布爾邏輯運算,并不是語言的特定構成,這是 and-or

          技巧和 C 語言中的 bool ? a : b 語法非常重要的不同。如果 a 為假,表達式就不會按你期望的那樣

          工作了。(你能知道我被這個問題折騰過嗎?不止一次?)

           

           

           


          Python 支持一種有趣的語法,它允許你快速定義單行的最小函數。這些叫做 lambda 的函數,是從

          Lisp 借用來的,可以用在任何需要函數的地方。
          例 4.20. lambda 函數介紹
          >>> def f(x):
          ...     return x*2
          ...    
          >>> f(3)
          6
          >>> g = lambda x: x*2 
          >>> g(3)
          6
          >>> (lambda x: x*2)(3)
          6

          總的來說,lambda 函數可以接收任意多個參數 (包括可選參數) 并且返回單個表達式的值。lambda

          函數不能包含命令,包含的表達式不能超過一個。不要試圖向 lambda 函數中塞入太多的東西;如

          果你需要更復雜的東西,應該定義一個普通函數,然后想讓它多長就多長。

           


          例 4.25. 打印列表
          >>> li = ['a', 'b', 'c']
          >>> print "\n".join(li)
          a
          b
          c  在你處理列表時,這確實是一個有用的調試技巧。在 Python 中,你會十分頻繁地操作列表。 

           

          在 2.2.1 版本之前,Python 沒有單獨的布爾數據類型。為了彌補這個缺陷,Python 在布爾環境 (如 if

          語句) 中幾乎接受所有東西,遵循下面的規則:
          0 為 false; 其它所有數值皆為 true。
          空串 ("") 為 false; 其它所有字符串皆為 true。
          空 list ([]) 為 false; 其它所有 list 皆為 true。
          空 tuple (()) 為 false; 其它所有 tuple 皆為 true。
          空 dictionary ({}) 為 false; 其它所有 dictionary 皆為 true。

           


          下面是 from module import 的基本語法:


          from UserDict import UserDict
          它與你所熟知的 import module 語法很相似,但是有一個重要的區別:UserDict 被直接導入到局部

          名字空間去了,所以它可以直接使用,而不需要加上模塊名的限定。你可以導入獨立的項或使用

          from module import * 來導入所有東西。

          Python 中的 from module import * 像 Java 中的 import module.* ;Python 中的 import module 像 Java

          中的 import module

          什么時候你應該使用 from module import?

          如果你要經常訪問模塊的屬性和方法,且不想一遍又一遍地敲入模塊名,使用 from module import


          如果你想要有選擇地導入某些屬性和方法,而不想要其它的,使用 from module import。
          如果模塊包含的屬性和方法與你的某個模塊同名,你必須使用 import module 來避免名字沖突。

          盡量少用 from module import * ,因為判定一個特殊的函數或屬性是從哪來的有些困難,并且會造

          成調試和重構都更困難。


          from UserDict import UserDict

          class FileInfo(UserDict):
          在 Python 中,類的基類只是簡單地列在類名后面的小括號里。不像在 Java 中有一個特殊的

          extends 關鍵字。 

          Python 支持多重繼承。在類名后面的小括號中,你可以列出許多你想要的類名,以逗號分隔。


          class FileInfo(UserDict):
              "store file metadata"
              def __init__(self, filename=None):
                  UserDict.__init__(self)       
                  self["name"] = filename       
                                                   一些偽面向對象語言,像 Powerbuilder 有一種“擴展”構造函數和其它事件的

          概念,即父類的方法在子類的方法執行前被自動調用。Python 不是這樣,你必須顯示地調用在父類中的合適方法。 
            我告訴過你,這個類像字典一樣工作,那么這里就是第一個印象。我們將參數 filename 賦值給對象 name 關鍵字,作為它的值。  注意 __init__ 方法從不返回一個值。 

          Java中是自動調用默認的無參的父類的構造函數

           


          例 5.9. 定義 UserDict 類

          class UserDict:                               
              def __init__(self, dict=None):             
                  self.data = {}  ×××××××××××××××××××××××××××××××××××定義類的實例變量                         
                  if dict is not None: self.update(dict) 
            注意 UserDict 是一個基類,不是從任何其他類繼承而來。 
            這就是我們在 FileInfo 類中進行了覆蓋的 __init__ 方法。注意這個父類的參數列表與子類不同。很

          好,每個子類可以擁有自已的參數集,只要使用正確的參數調用父類就可以了。這里父類有一個定

          義初始值的方法 (通過在 dict 參數中傳入一個字典),這一方法我們的 FileInfo 沒有用上。


          ××××××××××××××××××××××××××××××××與Java的不同×××××××××××××××××××××××××××××××××××
          與Java的不同,
          1,Python中類的類屬性是是在類的后面直接定義的
          2,而實例變量是在在__init__方法中直接定義的使用如下方式self.instancevariable=***定義,
          3,然后Python中實例方法都要顯示的加上self(相當于Java的this)參數,方法中引用實例變量時也要通過self來引用

          Python 支持數據屬性 (在 Java 叫做 “實例變量”,在 C++ 中叫 “數據成員”),它是由某個特定的類實

          例所擁有的數據。在本例中,每個 UserDict 實例將擁有一個 data 數據屬性。要從類外的代碼引用

          這個屬性,需要用實例的名字限定它,instance.data,限定的方法與你用模塊的名字來限定函數一

          樣。要在類的內部引用一個數據屬性,我們使用 self 作為限定符。習慣上,所有的數據屬性都在

          __init__ 方法中初始化為有意義的值。然而,這并不是必須的,因為數據屬性,像局部變量一樣,

          當你首次賦給它值的時候突然產生。 
          ×××××××××××××××××××××××××××××××××與Java的不同××××××××××××××××××××××××××××××××××

          Java 支持通過參數列表的重載,也就是 一個類可以有同名的多個方法,但這些方法或者是參數個

          數不同,或者是參數的類型不同。
          Python 兩種都不支持,總之是沒有任何形式的函數重載。一個 __init__ 方法就是一個 __init__ 方法

          ,不管它有什么樣的參數。每個類只能有一個 __init__ 方法,并且如果一個子類擁有一個 __init__

          方法,它總是 覆蓋父類的 __init__ 方法,甚至子類可以用不同的參數列表來定義它。

          想想為什么不支持方法重載,是因為Python的參數可以定義默認實參,有缺省值
          ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
          應該總是在 __init__ 方法中給一個實例的所有數據屬性賦予一個初始值。這樣做將會節省你在后面

          調試的時間,不必為捕捉因使用未初始化 (也就是不存在) 的屬性而導致的 AttributeError 異常費時費

          力。
          class MP3FileInfo(FileInfo):
          mp3file.__class__  is fileinfo.MP3FileInfo true
          mp3file.__class__  is fileinfo.FileInfo         false
          isinstance(mp3file,fileinfo.MP3FileInfo)  true
          isinstance(mp3file,fileinfo.FileInfo)          true

          li=[1,2,3]
          li2[1,2,3]
          li==li2 true   相當于Java的equals()
          li is li2 false 相當于Java的==


          5.7. 高級專用類方法
          除了 __getitem__ 和 __setitem__ 之外 Python 還有更多的專用函數。某些可以讓你模擬出你甚至可

          能不知道的功能。

          下面的例子將展示 UserDict 一些其他專用方法。

          例 5.16. UserDict 中更多的專用方法
              def __repr__(self): return repr(self.data)    
              def __cmp__(self, dict):                      
                  if isinstance(dict, UserDict):           
                      return cmp(self.data, dict.data)     
                  else:                                    
                      return cmp(self.data, dict)          
              def __len__(self): return len(self.data)      
              def __delitem__(self, key): del self.data[key]   __repr__ 是一個專用的方法,在當調用 repr

          (instance) 時被調用。repr 函數是一個內置函數,它返回一個對象的字符串表示。它可以用在任何

          對象上,不僅僅是類的實例。你已經對 repr 相當熟悉了,盡管你不知道它。在交互式窗口中,當你

          只敲入一個變量名,接著按ENTER,Python 使用 repr 來顯示變量的值。自已用一些數據來創建一

          個字典 d ,然后用 print repr(d) 來看一看吧。 
            __cmp__ 在比較類實例時被調用。通常,你可以通過使用 == 比較任意兩個 Python 對象,不只是

          類實例。有一些規則,定義了何時內置數據類型被認為是相等的,例如,字典在有著全部相同的關

          鍵字和值時是相等的。對于類實例,你可以定義 __cmp__ 方法,自已編寫比較邏輯,然后你可以

          使用 == 來比較你的類,Python 將會替你調用你的 __cmp__ 專用方法。 
            __len__ 在調用 len(instance) 時被調用。len 是一個內置函數,可以返回一個對象的長度。它可以

          用于任何被認為理應有長度的對象。字符串的 len 是它的字符個數;字典的 len 是它的關鍵字的個

          數;列表或序列的 len 是元素的個數。對于類實例,定義 __len__ 方法,接著自已編寫長度的計算

          ,然后調用 len(instance),Python 將替你調用你的 __len__ 專用方法。 
            __delitem__ 在調用 del instance[key] 時調用 ,你可能記得它作為從字典中刪除單個元素的方法。

          當你在類實例中使用 del 時,Python 替你調用 __delitem__ 專用方法。 

           
          在 Java 中,通過使用 str1 == str2 可以確定兩個字符串變量是否指向同一塊物理內存位置。這叫做

          對象同一性,在 Python 中寫為 str1 is str2。在 Java 中要比較兩個字符串值,你要使用 str1.equals

          (str2);在 Python 中,你要使用 str1 == str2。某些 Java 程序員,他們已經被教授得認為,正是因為

          在 Java 中 == 是通過同一性而不是值進行比較,所以世界才會更美好。這些人要接受 Python 的這

          個“嚴重缺失”可能要花些時間。 


          ord("a") 97
          ord("A") 65

           

          5.8. 類屬性介紹
          你已經知道了數據屬性,它們是被一個特定的類實例所擁有的變量。Python 也支持類屬性,它們是

          由類本身所擁有的。

          例 5.17. 類屬性介紹

          class MP3FileInfo(FileInfo):
              "store ID3v1.0 MP3 tags"
              tagDataMap = {"title"   : (  3,  33, stripnulls),
                            "artist"  : ( 33,  63, stripnulls),
                            "album"   : ( 63,  93, stripnulls),
                            "year"    : ( 93,  97, stripnulls),
                            "comment" : ( 97, 126, stripnulls),
                            "genre"   : (127, 128, ord)}


          例 5.18. 修改類屬性,Java中的靜態變量
          >>> class counter:
          ...     count = 0                    
          ...     def __init__(self):
          ...         self.__class__.count += 1 #一定得用self.__class__來引用,才是類變量,假如用self.count則定義的是實例變量,或者用
                      Counter.count +=1
          ...    
          上述代碼記錄創建的對象的個數

           

          5.9. 私有函數
          與大多數語言一樣,Python 也有私有的概念:

          私有函數不可以從它們的模塊外面被調用
          私有類方法不能夠從它們的類外面被調用
          私有屬性不能夠從它們的類外面被訪問
          與大多數的語言不同,一個 Python 函數,方法,或屬性是私有還是公有,完全取決于它的名字。

          如果一個 Python 函數,類方法,或屬性的名字以兩個下劃線開始 (但不是結束),它是私有的;其它

          所有的都是公有的。 Python 沒有類方法保護 的概念 (只能用于它們自已的類和子類中)。類方法或

          者是私有 (只能在它們自已的類中使用) 或者是公有 (任何地方都可使用)。

          在 MP3FileInfo 中,有兩個方法:__parse 和 __setitem__。正如我們已經討論過的,__setitem__

          是一個專有方法;通常,你不直接調用它,而是通過在一個類上使用字典語法來調用,但它是公有

          的,并且如果有一個真正好的理由,你可以直接調用它 (甚至從 fileinfo 模塊的外面)。然而,

          __parse 是私有的,因為在它的名字前面有兩個下劃線。

           
          在 Python 中,所有的專用方法 (像 __setitem__) 和內置屬性 (像 __doc__) 遵守一個標準的命名習慣

          :開始和結束都有兩個下劃線。不要對你自已的方法和屬性用這種方法命名;到最后,它只會把你 (或其它人) 搞亂。

          #!/usr/bin/env python
          #
          coding=utf-8
          import os
          import sys
          from UserDict import UserDict

          def stripnulls(data):
              
          "strip whitespace and null"
              
          return data.replace("\00","").strip()

          class FileInfo(UserDict):
              
          "store file metadata"
              
          def __init__(self,filename=None):
                  UserDict.
          __init__(self)
                  
          #will trigger the __setitem__ method,and this method be override in the sub class
                  self["name"]=filename

          class MP3FileInfo(FileInfo):
              
          "store ID3v1.0 MP3 tags"
              tagDataMap
          ={"title":(3,33,stripnulls),
                          
          "artist":(33,63,stripnulls),
                          
          "album" :(63,93,stripnulls),
                          
          "year"  :(93,97,stripnulls),
                          
          "comment":(97,126,stripnulls),
                          
          "genre" :(127,128,ord)}

              
          def __parse(self,filename):
                  
          "parse ID3v1.0 tags from Mp3 file"
                  self.clear()
                  
          try:
                      fsock 
          = open(filename,"rb",0)
                      
          try:
                          fsock.seek(
          -128,2)
                          tagdata 
          = fsock.read(128)
                      
          finally:
                          fsock.close()
                      
          if tagdata[:3]=="TAG":
                          
          for tag,(start,end,parseFunc) in self.tagDataMap.items():
                              self[tag] 
          = parseFunc(tagdata[start:end])
                  
          except IOError:
                      
          pass

              
          def __setitem__(self,key,item):
                  
          if key == "name" and item:
                      self.
          __parse(item)
                  FileInfo.
          __setitem__(self,key,item)

          def listDirectory(directory,fileExtList):
              
          "get list of file info object for files of particular"
              fileList 
          = [os.path.normcase(f)
                          
          for f in os.listdir(directory)]
              fileList 
          = [os.path.join(directory,f)
                          
          for f in fileList if os.path.splitext(f)[1in fileExtList]
              
          def getFileInfoClass(filename,module=sys.modules[FileInfo.__module__]):
                  
          "get file into class from filename extension"
                  subclass 
          = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
                  
          return hasattr(module,subclass) and getattr(module,subclass) or FileInfo
              
          return [getFileInfoClass(f)(f) for f in fileList]

          if __name__=="__main__":
              
          for info in listDirectory("G:\\test",[".mp3"]):
                  
          print "\n".join(["%s=%s" % (k,v) for (k,v) in info.items()])
                  
          print
                  
                  
              
          posted on 2009-08-22 00:02 Frank_Fang 閱讀(4211) 評論(0)  編輯  收藏 所屬分類: Python學習

          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 竹北市| 潮州市| 仁寿县| 昭平县| 寿光市| 南宁市| 湖州市| 临武县| 湖南省| 五河县| 方山县| 鹤岗市| 长乐市| 桐乡市| 潼关县| 监利县| 景东| 盐边县| 北安市| 广南县| 平谷区| 衡阳县| 香港| 左权县| 工布江达县| 临清市| 卓尼县| 双鸭山市| 高州市| 蒙山县| 关岭| 和林格尔县| 广元市| 上思县| 东平县| 东光县| 萨嘎县| 甘洛县| 无棣县| 乌拉特前旗| 肃北|