14.1 可調用對象 python
許多的python對象都是咱們所說的可調用的,便是任何能經過函數操做符「()」來調用的對象。要調用可調用對象,函數操做符得緊跟在可調用對象以後。python有4種可調用對象:函數,方法,類,以及一些類的實例。記住:這些對象的任何引用或者別名都是可調用的。 linux
14.1.1 函數 程序員
內建函數(BIFs) shell
內建函數在_builtin_模塊裏,並做爲_builtin_模塊導入到解釋器中。 windows
BIF 屬性 描述
bif.__doc__ 文檔字符串(或None)
bif.__name__ 字符串類型的文檔名字
bif.__self__ 設置爲None(保留給built-in 方法)
bif.__module__ 存放bif 定義的模塊名字(或None) app
咱們能夠用dir來列出模塊的全部屬性 ssh
用戶定義的函數(UDF) 函數
UDF 屬性 描述
udf.__doc__ 文檔字符串(也能夠用udf.func_doc)
udf.__name__ 字符串類型的函數名字(也能夠用 udf.func_name)
udf.func_code 字節編譯的代碼對象
udf.func_defaults 默認的參數元組
udf.func_globals 全局名字空間字典; 和從函數內部調用globals(x)同樣
udf.func_dict 函數屬性的名字空間
udf.func_doc (見上面的udf.__doc__)
udf.func_name (見上面的udf.__name__)
udf.func_closure 包含了自由變量的引用的單元對象元組
14.1.2 方法 oop
用戶自定義方法是被定義爲類的一部分的函數。許多python數據類型,好比列表和字典,也有方法,這些被稱爲內建方法。 性能
BIM 屬性 描述
bim.__doc__ 文檔字串
bim.__name__ 字符串類型的函數名字
bim.__self__ 綁定的對象
內建方法:
>>> dir([].append) ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']用戶定義的方法(UDM)
UDM包含在類定義之中,只是擁有標準函數的包裝,僅有定義它們的類可使用。若是沒有在子類定義中被覆蓋掉,也能夠經過子類實例來調用它們。UDM與類對象是關聯的(非綁定方法),可是隻能經過類的實例來調用(綁定方法)。不管UDMs是否綁定,全部的UDM都是相同的類型--「實例方法」。
>>> class C(object): # define class # 定義類 ... def foo(self): pass # define UDM # 定義UDM ... >>> c = C() # instantiation # 實例化 >>> type(C) # type of class # 類的類別 <type 'type'> >>> type(c) # type of instance # 實例的類別 <class '__main__.C'> >>> type(C.foo) # type of unbound method # 非綁定方法的類別 <type 'instancemethod'> >>> type(c.foo) # type of bound method # 綁定方法的類別 <type 'instancemethod'>
>>> C.foo <unbound method C.foo> >>> c.foo <bound method C.foo of <__main__.C object at 0x02115D50>> >>> c <__main__.C object at 0x02115D50>UDM 屬性 描述
14.1.3 類
利用類的可調用性來建立實例。
>>> class C(object): def __init__(self, *args): print "instantiated with these arguments:\n", args >>> c1 = C() instantiated with these arguments: () >>> c2 = C("the number of the counting shall be",3) instantiated with these arguments: ('the number of the counting shall be', 3)14.1.4 類的實例
python給類提供了名爲__call__的特別方法,該方法容許程序員建立可調用的對象實例。
>>> class C(object): def __call__(self, *args): print "i am callable!called with args:\n", args >>> c = C() >>> c <__main__.C object at 0x02115E10> >>> callable(c) True >>> c() i am callable!called with args: () >>> c(3) i am callable!called with args: (3,)
14.2 代碼對象
可調用的對象是python 執行環境裏最重要的部分,然而他們只是冰山一角。python 語句,賦值,表達式,甚至還有模塊構成了更宏大的場面。這些可執行對象沒法像可調用物那樣被調用。更確切地說,這些對象只是構成可執行代碼塊的拼圖的很小一部分,而這些代碼塊被稱爲代碼對象。
每一個可調用物的核心都是代碼對象,由語句,賦值,表達式,以及其餘可調用物組成。察看一個模塊意味着觀察一個較大的、包含了模塊中全部代碼的對象。而後代碼能夠分紅語句,賦值,表達式,以及可調用物。可調用物又能夠遞歸分解到下一層,那兒有本身的代碼對象。
通常說來,代碼對象能夠做爲函數或者方法調用的一部分來執行,也可用exec 語句或內建函數eval()來執行。從總體上看,一個python 模塊的代碼對象是構成該模塊的所有代碼。
若是要執行python 代碼,那麼該代碼必須先要轉換成字節編譯的代碼(又稱字節碼)。這纔是真正的代碼對象。然而,它們不包含任何關於它們執行環境的信息,這即是可調用物存在的緣由,它被用來包裝一個代碼對象並提供額外的信息。
14.3 可執行的對象聲明和內建函數
14.3.1 callable()
callable()是一個布爾函數,肯定一個對象是否能夠經過函數操做符(())來調用。若是函數可調用則返回true,不然返回false。
>>> callable(dir) True >>> callable(1) False >>> def foo():pass >>> callable(foo) True >>> class C(object):pass >>> callable(C) True
compile()函數容許程序員在運行時刻迅速生成代碼對象,而後就能夠用exec語句或者內建函數eval()來執行這些對象或者對它們進行求值。一個很重要的觀點是:exec和eval均可以執行字符串格式的python代碼。當執行字符串形式的代碼時,每次都必須對這些代碼進行字節編譯處理。compile函數提供了一次性字節代碼預編譯,之後每次調用的時候,都不用編譯了。
compile 的三個參數都是必需的,第一參數表明了要編譯的python 代碼。第二個字符串,雖然是必需的,但一般被置爲空串。該參數表明了存放代碼對象的文件的名字(字符串類型)。compile 的一般用法是動態生成字符串形式的Python 代碼, 而後生成一個代碼對象——代碼顯然沒有存放在任何文件。
最後的參數是個字符串,它用來代表代碼對象的類型。有三個可能值:
'eval' 可求值的表達式[和eval()一塊兒使用]
'single' 單一可執行語句[和exec 一塊兒使用]
'exec' 可執行語句組[和exec 一塊兒使用]
可求值表達式:
>>> eval_code = compile("100+200","","eval") >>> eval(eval_code) 300單一可執行語句
>>> single_code = compile("print 'hello world!'","", "single") >>> single_code <code object <module> at 021174E8, file "", line 1> >>> exec single_code hello world!可執行語句組:
exec_code = compile(""" req = input("count how many numbers?") for eachNum in range(req): print eachNum, ""","","exec")程序輸出:
>>> exec exec_code count how many numbers?6 0 1 2 3 4 514.3.3 eval()
eval()對錶達式求值,後者能夠爲字符串或內建函數complie()建立的預編譯代碼對象。這是eval()第一個也是最重要的參數.......這即是你想要執行的對象。第二個和第三個參數,都爲可選的,分別表明了全局和局部名字空間中的對象。若是給出這兩個參數,globals 必須是個字典,locals能夠是任意的映射對象,好比,一個實現了__getitem__()方法的對象。(在2.4 以前,local 必須是一個字典)若是都沒給出這兩個參數,分別默認爲globals()和locals()返回的對象,若是隻傳入了一個全局字典,那麼該字典也做爲locals 傳入
>>> eval("100+200") 30014.3.4 exec
和eval()類似,exec 語句執行代碼對象或字符串形式的python 代碼。相似地,用compile()預編譯重複代碼有助於改善性能,由於在調用時沒必要通過字節編譯處理。exec 語句只接受一個參數,下面即是它的通用語法:
exec obj
exec """ x = 0 print "x is currently:",x while x < 5: x += 1 print "incrementing x to:",x """程序輸出:
>>> x is currently: 0 incrementing x to: 1 incrementing x to: 2 incrementing x to: 3 incrementing x to: 4 incrementing x to: 5固然,exec也能夠執行文件對象,咱們上面的代碼在文件xcount.py中:
>>> f = open("xcount.py") >>> exec f x is currently: 0 incrementing x to: 1 incrementing x to: 2 incrementing x to: 3 incrementing x to: 4 incrementing x to: 5 >>> exec f >>> f.close() >>> f = open("xcount.py") >>> exec f x is currently: 0 incrementing x to: 1 incrementing x to: 2 incrementing x to: 3 incrementing x to: 4 incrementing x to: 5中間出現exec f後沒任何反應,是由於文件也是順序執行下來的,已經到末尾了,因此exec f固然沒任何反應。從新打開文件再執行便可。
固然,咱們也能夠這樣作:
>>> f = open("xcount.py") >>> exec f x is currently: 0 incrementing x to: 1 incrementing x to: 2 incrementing x to: 3 incrementing x to: 4 incrementing x to: 5 >>> f.seek(0) >>> exec f x is currently: 0 incrementing x to: 1 incrementing x to: 2 incrementing x to: 3 incrementing x to: 4 incrementing x to: 514.3.5 input()
內建函數input()是eval()和raw_input()的組合,等價於eval(raw_input()).
從功能上看,input 不一樣於raw_input(),由於raw_input()老是以字符串的形式,逐字地返回用戶的輸入。input()履行相同的的任務;並且,它還把輸入做爲python 表達式進行求值。這意味着input()返回的數據是對輸入表達式求值的結果:一個python 對象。
下面的例子確實讓我吃驚:
>>> aString = raw_input("enter a list:") enter a list:[123,"xyz",45.67] >>> aString '[123,"xyz",45.67]' >>> type(aString) <type 'str'> >>> aList = input("enter a list:") enter a list:[123,"xyz",45.67] >>> aList [123, 'xyz', 45.67] >>> type(aList) <type 'list'>雖然用戶輸入字符串,可是input()把輸入做爲python對象來求值並返回表達式的結果。
14.3.6 使用python在運行時生成和執行python代碼
第一個例子是loopmake.py 腳本,一個簡單的、迅速生成和執行循環的計算機輔助軟件工程(CASE)。它提示用戶給出各類參數(好比,循環類型(while 或for), 迭代的數據類型[數字或序列]),生成代碼字串,並執行它
dashes = "\n" + "-"*50 exec_dict = { "f":""" for %s in %s: print %s """, "s":""" %s=0 %s = %s while %s < len(%s): print %s[%s] %s = %s + 1 """, "n":""" %s = %d while %s < %d: print %s %s = %s + %d """ } def main(): ltype = raw_input("loop type?(for/while)") dtype = raw_input("data type?(number/seq)") if dtype == "n": start = input("starting value?") stop = input("ending value(non-inclusive)?") step = input("stepping value?") seq = str(range(start, stop, step)) else: seq = raw_input("enter sequence:") var = raw_input("iterative variable name?") if ltype == "f": exec_str = exec_dict["f"] % (var, seq, var) elif ltype == "w": if dtype == "s": svar = raw_input("enter sequence name?") exec_str = exec_dict["s"] %\ (var, svar, seq, var, svar, svar, var,var,var) elif dtype == "n": exec_str = exec_dict["n"] %\ (var, start, var, stop, var, var, var, step) print dashes print "your custom-generated code:" + dashes print exec_str + dashes print "test execution of the code:" + dashes exec exec_str print dashes if __name__ == "__main__": main()我坦白說,這個程序特別的好玩。技術含量提升的,可是更重要的是:好玩:
>>> loop type?(for/while)w data type?(number/seq)n starting value?0 ending value(non-inclusive)?4 stepping value?1 iterative variable name?counter -------------------------------------------------- your custom-generated code: -------------------------------------------------- counter = 0 while counter < 4: print counter counter = counter + 1 -------------------------------------------------- test execution of the code: -------------------------------------------------- 0 1 2 3 --------------------------------------------------
>>> loop type?(for/while)f data type?(number/seq)n starting value?0 ending value(non-inclusive)?4 stepping value?1 iterative variable name?counter -------------------------------------------------- your custom-generated code: -------------------------------------------------- for counter in [0, 1, 2, 3]: print counter -------------------------------------------------- test execution of the code: -------------------------------------------------- 0 1 2 3 --------------------------------------------------
>>> loop type?(for/while)w data type?(number/seq)s enter sequence:[932,"grail",3.0,"arrrghhh"] iterative variable name?eachIndex enter sequence name?myList -------------------------------------------------- your custom-generated code: -------------------------------------------------- eachIndex=0 myList = [932,"grail",3.0,"arrrghhh"] while eachIndex < len(myList): print myList[eachIndex] eachIndex = eachIndex + 1 -------------------------------------------------- test execution of the code: -------------------------------------------------- 932 grail 3.0 arrrghhh --------------------------------------------------有條件的執行代碼:
def foo(): return True def bar(): "bar() does not do much" return True foo.__doc__ = "foo() does not do much" foo.tester = """ if foo(): print "passed" else: print "failed" """ for eachAttr in dir(): obj = eval(eachAttr) if isinstance(obj, type(foo)): if hasattr(obj, "__doc__"): print "\nfunction '%s' has a doc string:\n\t%s" % (eachAttr, obj.__doc__) if hasattr(obj, "tester"): print "function '%s' has a tester...executing" % eachAttr exec obj.tester else: print "function '%s' has no tester...skipping" % eachAttr else: print "%s is not a function" % eachAttr程序輸出:
>>> __builtins__ is not a function __doc__ is not a function __name__ is not a function __package__ is not a function function 'bar' has a doc string: bar() does not do much function 'bar' has no tester...skipping function 'foo' has a doc string: foo() does not do much function 'foo' has a tester...executing passed
14.4 執行其餘(python)程序
當討論執行其餘程序時,咱們把它們分類爲python程序和其餘全部的非python程序,後者包括了二進制可執行文件或其餘腳本語言的源代碼。
14.4.1 導入
第一次導入模塊會執行模塊最高級的代碼。若是你想某些功能不被執行,那麼就縮進它,而後放入 if __name__ == "__main__"中去便可。
14.4.2 execfile()
顯然,導入模塊不是從另外的python腳本中執行python腳本最可取的方法。那也就不是導入過程。導入模塊的反作用是致使最高級代碼運行。
f = open(filename,"r") exec f f.close()等價於:
execfile(filename)雖然上述代碼執行了一個模塊,可是僅能夠在現有的執行環境下運行(好比,它本身的全局和局部的名字空間)。在某些狀況下,可能須要用不一樣全局和局部的名字空間集合,而不是默認的集合來執行模塊。execfile() 函數的語法很是相似於eval()函數的。
execfile(filename, globals=globals(), locals=locals())
14.4.3 將模塊做爲腳本執行
經過shell或者DOS來執行便可。
14.5 執行其餘(非python)程序
14.5.1 os.system()
接收字符串形式的系統命令並執行它。當執行命令的時候,python的運行是掛起的。當咱們的執行完成以後,將會以system()的返回值給出退出狀態,python的執行也會繼續。
>>> import os >>> result = os.system("dir") >>> result 0結果是出現DOS黑框框,而後一閃而過。。。。。。。
14.5.2 os.popen()
不理解這個函數。。。。。。
後面剩下的10也就不看了,主要是如今沒涉及到多平臺的開發,看了也忘,並且例子多數在linux下,沒法操做。
14.10 練習
14–1. 可調用對象。 說出python 中的可調用對象。exec 語句和內建函數eval()有什麼不一樣?
可經過函數操做符(())來調用的對象是可調用對象。而exec一般直接執行一個字符串,eval()一般執行的是表達式。
14–2. input()和raw.input()。 內建函數raw_input()和input()有什麼不一樣?
input()操做的是表達式,並把表達式直接顯示出來,而raw_input()則用適當的形式(爲字符串)來顯示。
14–3. 執行環境。建立運行其餘python 腳本的python 腳本
execfile("file1.txt") execfile("file2.txt") execfile("file3.txt")程序輸出:
>>> hello world 4 0 1 2 3 4而file1.txt的內容爲:
print "hello world"file2.txt的內容爲:
print 1+1+2file3.txt的內容爲:
for i in range(5): print i,14–4. os.system()。選擇熟悉的系統命令,該命令執行任務時不須要輸入,也不輸出到屏幕或根本不輸出任何東西。調用os.system()運行程序
>>> import os >>> os.system("date")程序輸出:
14–5. commands.getoutput().用commands.getoutput()解決前面的問題
在windows平臺上貌似不行吧,我直接運行都無commands模塊。。。。。