- 示例代碼:
from types import BuiltinFunctionType, BuiltinMethodType, \ FunctionType, MethodType, ClassType def help(object, spacing=10, collapse=1): """Print method and doc string. Takes module, class, list, dictionary, or string.""" typeList = (BuiltinFunctionType, BuiltinMethodType, FunctionType. MethodType, ClassType) methodList = [method for method in dir(object) if type(getattr(object, method)) in typeList] processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s:s) print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method i n methodList]) if __name__ == "__main__": print help.__doc__
- 自省綜述:根據上邊示例代碼分析
- 這個模塊有一個函數,help, 有三個參數object, spacing, collapse, 后兩個是可選參數
- 函數的代碼是縮排的,help函數有一個多行的文檔字符串,並沒有返回值,因為函數只使用他的效果並非它的值
- __name__技巧只是用於測試模塊,在別的程序引入這個模塊的時候不會引起沖突,
- help函數的設計是為了在ide環境下是用的,接受任何擁有函數或者方法的對象,打印出對象所有的函數和文檔字符串
- 用法舉例
>>> from apihelper import help >>> li = [] >>> help(li) append L.append(object) -- append object to end count L.count(value) -> integer -- return number of occurrences of value extend L.extend(list) -- extend list by appending list elements index L.index(value) -> integer -- return index of first occurrence of value insert L.insert(index, object) -- insert object before index pop L.pop([index]) -> item -- remove and return item at index (default last) remove L.remove(value) -- remove first occurrence of value reverse L.reverse() -- reverse *IN PLACE* sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
- 高級用法:注意參數變化
>>> import odbchelper >>> help(odbchelper) buildConnectionString Build a connection string from a dictionary Returns string. >>> help(odbchelper, 30) buildConnectionString Build a connection string from a dictionary Returns string. >>> help(odbchelper, 30, 0) buildConnectionString Build a connection string from a dictionary Returns string.
- 導入模塊:兩種導入模塊的方法
- 基本的from module import 語法
from types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ClassType
注意:與module導入方法類似,但是,導入模塊types的屬性和方法被直接導入到局部名字空間中,使用的時候不用模塊的名字來限定;
- import 和 from module import 對比
>>> import types #只是有每個對象類型的屬性 >>> types.FunctionType #必須用module 名稱來限定 <type 'function'> >>> FunctionType #沒有定義在當前的名字空間中,只是存在與types的上下問環境當中 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'FunctionType' is not defined >>> from types import FunctionType >>> FunctionType <type 'function'>
- 什么時候要用from module import
- 如果想經常存取模塊的屬性和方法,但是不想一遍遍的敲入模塊名稱
- 想選擇性的導入某些屬性和方法,不想要其他的
- 如果模塊包含的屬性或者方法和你自己的某個模塊名字相同,只能用import module
- 基本的from module import 語法
- 可選和定名參數(指定參數名字):
- help的合法調用
help(odbchelper) help(odbchelper, 12) help(odbchelper, collapse=0) #spacing 缺省 help(spacing=15, object=odbchelper) #object可以定名,任意順序都行
- help的合法調用
- type,str,dir和其他內置函數:
- type:返回任意對象的數據類型
>>> type("333") <type 'str'> >>> li=[] >>> type(li) <type 'list'> >>> import odbchelper >>> type(odbchelper) <type 'module'> >>> import types >>> type(odbchelper) == types.ModuleType True
- str:強制將數據轉換為字符串
>>> str(1) '1' >>> ho = ["sd", 1, "sdd"] #可以工作於任何類型的任何對象 >>> str(ho) "['sd', 1, 'sdd']" >>> str(odbchelper) #模塊的字符串表示包含了模塊在磁盤上的路徑 "<module 'odbchelper' from 'odbchelper.pyc'>" >>> str(None) #python空值 返回字符串 很重要??? 'None'
- dir:help函數的核心,返回任意一個對象的屬性和方法的列表:模塊,函數,字符串,列表,字典... 相當多的東西
>>> 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']
- 內置屬性和函數
>>> from apihelper import help >>> help(__builtins__, 20) ArithmeticError Base class for arithmetic errors. AssertionError Assertion failed. AttributeError Attribute not found. EOFError Read beyond end of file. EnvironmentError Base class for I/O related errors. Exception Common base class for all exceptions. FloatingPointError Floating point operation failed. IOError I/O operation failed. [...snip...] ???
- 綜合:type dir str, 以及所有其他的python內置函數一樣被組合進入一個名字叫做__builtins__的特別模塊中,python啟動的時候自動from __builtins__ import * 可以直接使用,好處是,可以通過得到builtins的信息,作為一個組,存取所有內置的函數和屬性,help函數實現了那個功能。???
- type:返回任意對象的數據類型
- 使用getattr得到對象的各種引用:可以得到一個直到運行時候才知道的函數的引用???
- getattr介紹
>>> li=["larry", "curly"] >>> li.pop #得到列表的pop方法的一個引用,並不是調用pop方法,而是方法本身 <built-in method pop of list object at 0xb7724f4c> >>> getattr(li, "pop") #也返回pop方法的一個引用,但是,方法的名字被指定為一個字符串參數,getattr可以返回任意對象的任意屬性,在這個例子中,對象是列表,屬性是pop方法 <built-in method pop of list object at 0xb7724f4c> >>> getattr(li, "append")("moe") #li.append("moe") 返回值是方法,沒有直接調用方法,而是把函數名當作字符串來指定。 >>> li ['larry', 'curly', 'moe'] >>> getattr({}, "clear") #也可以用給字典 <built-in method clear of dict object at 0x828e604> >>> getattr((), "pop") #理論上可以用個序列,但是序列沒有方法,所以不管給出什么屬性名,getattr都將引發一個異常, Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'tuple' object has no attribute 'pop'
- 用於apihelper.py, 不僅可以用於內置數據類型,也可以用於模塊
>>> import odbchelper >>> odbchelper.buildConnectionString #返回在odbchelper模塊中的bulidConnectionString函數的引用 <function buildConnectionString at 0x820bb8c> >>> getattr(odbchelper, "buildConnectionString") #使用getattr,我們可以得到同一函數的同一引用。 相當於object.attribute. 如果object是一個模塊,那么attribute可以是模塊中的任何東西:函數,類,或者全局變量。 <function buildConnectionString at 0x820bb8c> >>> object = odbchelper >>> method = "buildConnectionString" >>> getattr(object, method) #help函數中用到的東西,method字符串是方法或者函數的名字。 <function buildConnectionString at 0x820bb8c> >>> type(getattr(object, method)) 本地方method是一個函數的名字 <type 'function'> >>> import types >>> type(getattr(object, method)) == types.FunctionType True
- getattr介紹
- 過濾列表:python強大的列表映射到其他列表的能力,同一種過濾機制合並,列表中的某個元素被映射,其他的都忽略掉。
- 列表過濾語法
[mapping-expression for element in source-list if filter-expression]
以if開頭的就是過濾表達式,可以是任意真假的表達式,任何對於過濾表達式計算出真值的元素將包括在映射中,其他元素忽略掉,他們不會出現在映射表達式中,也不包括在輸出列表中。
- 列表過濾介紹
>>> 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"] # 過濾掉特殊值b,每次b出來過濾表達式都不成立 ['a', 'mpilgrim', 'foo', 'c', 'd', 'd'] >>> [elem for elem in li if li.count(elem) == 1] #count返回的是一個元素出現的次數 ['a', 'mpilgrim', 'foo', 'c']
- apihelper.py中過濾列表
typeList = (BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ClassType) methodList = [method for method in dir(object) if type(getattr(objec, method)) in typeList]
看上去挺復雜,但是基本結構是一樣的。整個表達式返回一個列表,列表賦給變量methodList,前半部分是列表映射部分,dir(object)返回一個對象的屬性和方法的列表,就是正在映射的列表。表達式getattr(object, method)返回一個函數對象,method是模塊中的函數名字,這個表達式接受一個object對象,獲得它的屬性方法,和一些其他東西的名字列表,然后過濾列表,執行過濾通過得到每個屬性方法函數的名字,讓后通過getattr函數得到指向實際東西的引用。然后用type檢查對象類型,我們關心方法和函數,不關心其他屬性。classType對象現在不用擔心,后邊將討論python的類。
- 列表過濾語法
- and-or技巧:要對比bool?a:b 理解其如何工作
>>> a = "first" >>> b = "second" >>> 1 and a or b #類似c 'first' >>> 0 and a or b #類似c 'second' >>> a = "" >>> 1 and a or b #區別,看成純粹的布爾邏輯去分析。 'second' >>> a = "" >>> b = "second" >>> 1 and a or b 'second' >>> 0 and a or b 'second' >>> (1 and [a] or [b])[0] [a] 是一個非空列表 永遠為真, ''
Python 中很多時候,不允許使用if語句,一個負責的的程序猿應該將and or 技巧封裝成函數:
def choose(bool, a, b): return (bool and [a] or [b])[0]
???
- 使用lambda函數:快速定義單行的最小函數,可以被用在任何需要函數的地方,函數的語法通常與其他函數有點不同???
- lambda函數介紹
>>> def f(x): ... return x*2 ... >>> f(2) 4 >>> g = lambda x: x*2 #lambda函數, 沒有小括號,return是默認的,函數沒有名字。只有將它賦值給變量的變量名g >>> g(3) 6 >>> (lambda x: x*2)(3) #可以不賦值給一個變量然后使用它,證明是一個內聯函數 6
可以接收任意多個參數(包括可選參數)值並且返回單個表達式的值的函數,lambda函數不能包括命令,表達式不能超過一個,不要賽入過多東西。
lambda函數是風格問題,不一定非要使用,許多小的一行代碼不會弄亂我的代碼,用在需要特殊封裝的,非重用的代碼上。
- 例子中的lambda函數
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
lambda函數在一個布爾環境下總為真,並不意味着不能返回假值,函數本身總是真,返回值可以任何值。
- split不帶參數:上邊式子中不帶參數
>>> s = "this is\na\ttest" >>> print s this is a test >>> print s.split() # split不帶參數按空白進行分割!!! ['this', 'is', 'a', 'test'] >>> print " ".join(s.split()) #將空白統一化!!! 'this is a test'
- 將函數賦給一個變量
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
processFunc現在是一個函數,但是函數為哪一個要看collapse的值。如果為真processFunc(string)將壓縮空白,否則,將返回未改變的參數。
- 注意:其他不健壯的語言實現它,可能創建一個函數,它接收一個字符串和一個collapse函數,使用一個If語句來判斷是否需要壓縮空白或者不壓縮,然后返回相應的值,但是這樣效率比較低,每次調用它,不得不再給出想要的東西之前,判斷是否空白。在python中,可以將這種判斷邏輯拿到函數之外,定義一個裁剪過的函數lambda來給出確切的(唯一的)你想要的。這樣做更有效率更漂亮,並且更少導致那些令人討厭的錯誤???
- lambda函數介紹
- 全部放在一起:所有的多米諾骨牌拼接到一起了,然后將它推倒吧。
-
- 最后一行的內容
print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList])
-
- 最后一句告訴我們這是一個列表映射,methodLIst是一個在object中所有我們關心的方法的列表。我們用method遍歷列表
- 動態得到文檔字符串
>>> import odbchelper >>> object = odbchelper #object是我們要得到的幫助的對象 >>> method = 'buildConnectionString' #method 是當前方法的名字 >>> getattr(object, method) #得到在object模塊中對於method函數的一個引用 <function buildConnectionString at 010D6D74> >>> print getattr(object, method).__doc__ #打印文檔字符串 Build a connection string from a dictionary of parameters. Returns string. #至於str 是一個 內置函數,強制轉換數據,但是不是每個函數都有文檔字符串,如果沒有的話,__doc__屬性是None.
- 為什么對一個文檔字符串使用str
>>>{}.keys__doc__ >>>{}.keys__doc__ == None 1 >>>str({}.keys__doc__) #使用str函數就接收了空值,返回它的字符串表示 None
然后保證有了字符串,傳遞字符串給processFunc,這個函數定義了一個要不要壓縮空白或者不壓縮,因為process假定一個字符串參數,並且調用了split方法,如果傳給的是方法None,而不是字符串,函數就會失敗了。
- ljust方法介紹
>>>s = "build" >>>s.ljust(30) #用空格填充到指定長度,這樣就可以繼續對齊了 "build " >>>s.ljust(2) #少於字符串的話 返回原字符串 "build"
- 打印列表
>>>li=['a','b'] >>>print "\n".join(li) # 一個有用的調試技巧
11,小結
- apihelper.py代碼和輸出
# 代碼 from types import BiultinFunctionType, BulitinMethodType, FunctionType, MethodType, ClassType def help(object, collapse=1, spacing=10): ""Print methods and doc string. Take module, class, list, dictionary, or string.""" typeList = (BiultinFunctionType, BulitinMethodType, FunctionType, MethodType, ClassType) methodList = [method for method in dir(object) if type(getattr(object, emthod)) in typeList] processFunc = collapse and (lambda s: " ".join(split())) or (lambda s: s) print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList]) if __name__ == "__main__": print help.__doc__ # 輸出 >>> from apihelper import help >>> li = [ ] >>>help(li) append L.append(object) -- append object to end count L.count(value) -> integer -- return number of occurrences of value extend L.extend(list) -- extend list by appending list elements index L.index(value) -> integer -- return index of first occurrence of value insert L.insert(index, object) -- insert object before index pop L.pop([index]) -> item -- remove and return item at index (default last) remove L.remove(value) -- remove first occurrence of value reverse L.reverse() -- reverse *IN PLACE* sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
- 自我完成作業
- 選用Import或者from module import導入模塊
- 可選和定名參數定義和調用函數
- str強制轉換為字符串表達式
- 使用getattr動態函數得到函數和其他的什么引用
- 擴展映射列表進行列表過濾
- and-or的技巧的應用
- 定義lambda函數
- 將函數賦值給變量,然后通過引用變量調用函數。這種思考方式會提高對python的理解力???
可通過本人轉載的“Django實戰系列”進行django的進一步學習;另外,實戰系列的源代碼下載地址:在實戰系列文章中留言寫下郵箱地址,一天內會發送給你全部源代碼。