Dave Python 練習十六 — 執行環境

來源:互聯網
上載者:User

#encoding=utf-8<br />###*************** 執行環境 *********************</p><p>##************ Part 1: 可調用對象 *****************<br />#許多的python 對象都是我們所說的可調用的,即是任何能通過函數操作符“()”來調用的對象。<br />#要調用可調用對象,函數操作符得緊跟在可調用對象之後。比方說,用“foo()”來調用函數"foo"。<br />#可調用對象可以通過函數式編程介面來進行調用,如apply(),filter(),map()。<br />#Python 有4 種可調用對象:函數,方法,類,以及一些類的執行個體。記住這些對象的任何引用或者別名都是可調用的。</p><p>#### 1.1 函數<br />#python 有3 種不同類型函數對象.</p><p>## 1.1.1 內建函數(BIFs)<br />#BIF 是用c/c++寫的,編譯過後放入python 解譯器,然後把它們作為第一(內建)名字空間的<br />#一部分載入進系統。這些函數在_bulitin_模組裡,並作為__builtins__模組匯入到解譯器中。</p><p>#內建函數屬性<br />#BIF 屬性 描述<br />#bif.__doc__ 文檔字串(或None)<br />#bif.__name__ 字串類型的文檔名字<br />#bif.__self__ 設定為None(保留給built-in 方法)<br />#bif.__module__ 存放bif 定義的模組名字(或None)</p><p>#可以用dir()列出函數的所有屬性:<br />#print(dir(type))<br />#['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__',<br />#'__delattr__', '__dict__', '__dictoffset__', '__doc__', '__eq__', '__flags__', '__format__',<br />#'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__instancecheck__', '__itemsize__',<br />#'__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__prepare__',<br />#'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__',<br />#'__subclasses__', '__subclasshook__', '__weakrefoffset__', 'mro']</p><p>#從內部機制來看,因為BIFs 和內建方法(BIMs)屬於相同的類型,所以對BIF 或者BIM 調用type()的結果是:<br />#>>> type(dir)<br />#<type 'builtin_function_or_method'></p><p>#注意這不能應用於工廠函數,因為type()正好會返回產生對象的類型:<br />#>>> type(int)<br />#<type 'type'><br />#>>> type(type)<br />#<type 'type'></p><p>## 1.1.2 使用者定義的函數(UDF)<br />#UDF(User-Defined Function,使用者定義的函數)通常是用python 寫的,定義在模組的最進階,<br />#因此會作為全域名字空間的一部分(一旦建立好內建名字空間)裝載到系統中。函數也可在其他的函<br />#數體內定義,現在可以對多重嵌套範圍中的屬性進行訪問。可以用func_closure 屬性來鉤住在其他地方定義的屬性。</p><p>#使用者自訂函數屬性<br />#UDF 屬性 描述<br />#udf.__doc__ 文檔字串(也可以用udf.func_doc)<br />#udf.__name__ 字串類型的函數名字(也可以用 udf.func_name)<br />#udf.func_code 位元組編譯的代碼對象<br />#udf.func_defaults 預設的參數元組<br />#udf.func_globals 全域名字空間字典; 和從函數內部調用globals(x)一樣<br />#udf.func_dict 函數屬性的名字空間<br />#udf.func_doc (見上面的udf.__doc__)<br />#udf.func_name (見上面的udf.__name__)<br />#udf.func_closure 包含了自由變數的引用的單元對象元組</p><p>#從內部機制來看,使用者自訂的函數是“函數“類型的.<br />#<br />#lambda 運算式和使用者自訂對函數相比,略有不同。雖然它們也是返回一個函數對象,但是<br />#lambda 運算式不是用def 語句建立的,而是用lambda 關鍵字:<br />#因為lambda 運算式沒有給具名繫結的代碼提供基礎結構,所以要通過函數式編程介面來調用,<br />#或把它們的引用賦值給一個變數,然後就可以直接調用或者再通過函數來調用。變數僅是個別名,<br />#並不是函數對象的名字。<br />#通過lambda 來建立函數的對象除了沒有命名之外,享有和使用者自訂函數相同的屬性;__name__<br />#或者func_name 屬性給定為字串"<lambda>"。使用type()工廠函數,我們來示範下lambda 運算式<br />#返回和使用者自訂函數相同的函數對象。<br />#<br />#>>> lambdaFunc = lambda x: x * 2<br />#>>> lambdaFunc(100)<br />#200<br />#>>> type(lambdaFunc)<br />#<type 'function'></p><p>#### 1.2 方法<br />#使用者自訂方法是被定義為類的一部分的函數。許多python 資料<br />#類型,比如列表和字典,也有方法,這些被稱為內建方法。為了進一步說明“所有權“的類型,方<br />#法通過對象的名字和句點屬性標識進行命名。</p><p>#內建方法(BIM)屬性<br />#BIM 屬性 描述<br />#bim.__doc__ 文檔字串<br />#bim.__name__ 字串類型的函數名字<br />#bim.__self__ 綁定的對象</p><p>## 1.2.1 內建方法(BIMs)<br />#BIM 和BIF 兩者也都享有相同屬性。不同之處在於BIM 的__self__屬性指向一個Python對象,而BIF 指向None。</p><p>#只有內建類型(BIT)有BIM.對於內建方法,type()工廠函數給出了和BIF 相同的輸出--注意,我們是如何提供一個內建對象來訪問BIM:<br />#>>> type([].append)<br />#<type 'builtin_function_or_method'></p><p>#對於類和執行個體,都能以該對象為參數,通過內建函數dir()來獲得他們的資料和方法屬性。這也可以用在BIM 上:<br />#>>> dir([].append)<br />#['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',<br />#'__getattribute__', '__hash__', '__init__', '__module__',<br />#'__name__', '__new__', '__reduce__', '__reduce_ex__',<br />#'__repr__', '__self__', '__setattr__', '__str__']</p><p>## 1.2.2 使用者定義的方法(UDM)<br />#UDM(User-defined method,使用者定義的方法)包含在類定義之中,只是擁有標準函數的封裝,<br />#僅有定義它們的類可以使用。如果沒有在子類定義中被覆蓋掉,也可以通過子類執行個體來調用它們。</p><p>#UDM 與類對象是關聯的(非Binder 方法),但是只能通過類的執行個體來調用(綁<br />#定方法)。無論UDMs 是否綁定,所有的UMD 都是相同的類型——“執行個體方法“,</p><p>#>>> class C(object): # define class # 定義類<br />#... def foo(self): pass # define UDM # 定義UDM<br />#...<br />#>>> c = C() # instantiation # 執行個體化<br />#>>> type(C) # type of class # 類的類別<br />#<type 'type'><br />#>>> type(c) # type of instance # 執行個體的類別<br />#<class '__main__.C'><br />#>>> type(C.foo) # type of unbound method # 非Binder 方法的類別<br />#<type 'instancemethod'><br />#>>> type(c.foo) # type of bound method # Binder 方法的類別<br />#<type 'instancemethod'></p><p>#使用者自訂屬性<br />#UDM 屬性 描述<br />#udm.__doc__ 文檔字串(與udm.im_fuc.__doc__相同)<br />#udm.__name__ 字串類型的方法名字(與umd.im_func.__name__相同)<br />#udm.__module__ 定義udm 的模組的名字(或none)<br />#udm.im_class 方法相關聯的類(對於綁定的方法;如果是非綁定,那麼為要求udm 的類)<br />#udm.im_func 方法的函數對象(見UDFs)<br />#udm.im_self 如果綁定的話為相關聯的執行個體,如果非綁定位為none</p><p>#### 1.3 類<br />#可以利用類的可調用性來建立執行個體。“調用”類的結果便是建立了執行個體,即大家所知道的實<br />#例化。類有預設建構函式,該函數什麼都不做,基本上只有一個pass 語句。程式員可以通過實現<br />#__int__()方法,來自訂執行個體化過程。執行個體化調用的任何參數都會傳入到建構函式裡。</p><p>#### 1.4 類的執行個體<br />#python 給類提供了名為__call__的特別方法,該方法允許程式員建立可調用的對象(執行個體)。默<br />#認情況下,__call__()方法是沒有實現的,這意味著大多數執行個體都是不可調用的。然而,如果在類<br />#定義中覆蓋了這個方法,那麼這個類的執行個體就成為可調用的了。調用這樣的執行個體對象等同於調用<br />#__call__()方法.任何在執行個體調用中給出的參數都會被傳入到__call()__中.</p><p>#那麼foo()就和foo.__call__(foo)的效果相同, 這裡foo 也作為參數出現,因為是對自己的引用,執行個體將自<br />#動成為每次方法調用的第一個參數。如果 ___call___()有參數,比如,(self, arg),那麼foo(arg)就和調用foo.__call__(foo, arg)一樣。</p><p>#class C(object):<br /># def __call__(self, *args):<br /># print("I'm callable! Called with args:\n", args)</p><p>##************ Part 2: 代碼對象 *****************<br />#可調用的對象是python 執行環境裡最重要的部分,然而他們只是冰山一角。python 語句,賦值,<br />#運算式,甚至還有模組構成了更宏大的場面。這些可執行對象無法像可調用物那樣被調用。更確切<br />#地說,這些對象只是構成可執行代碼塊的拼圖的很小一部分,而這些代碼塊被稱為代碼對象。</p><p>#每個可調用物的核心都是代碼對象,由語句,賦值,運算式,以及其他可調用物組成。察看一<br />#個模組意味著觀察一個較大的、包含了模組中所有代碼的對象。然後代碼可以分成語句,賦值,表<br />#達式,以及可調用物。可調用物又可以遞迴分解到下一層,那兒有自己的代碼對象。</p><p>#一般說來,代碼對象可以作為函數或者方法調用的一部分來執行,也可用exec 語句或內建函數<br />#eval()來執行。從整體上看,一個python 模組的代碼對象是構成該模組的全部代碼。</p><p>#如果要執行python 代碼,那麼該代碼必須先要轉換成位元組編譯的代碼(又稱位元組碼)。這才是<br />#真正的代碼對象。然而,它們不包含任何關於它們執行環境的資訊,這便是可調用物存在的原因,<br />#它被用來封裝一個代碼對象並提供額外的資訊。</p><p>##************ Part 3: 可執行檔對象聲明和內建函數 *****************<br />#Python 提供了大量的BIF 來支援可調用/可執行對象,其中包括exec 語句。這些函數協助程式<br />#員執行代碼對象,也可以用內建函數complie()來產生代碼對象。</p><p>#內建函數和語句 描述<br />#callable(obj) 如果obj 可調用,返回True,否則返回FALSE<br />#compile(string,file, type) 從type 類型中建立代碼對象;file 是代碼存放的地方(通常設為"")<br />#eval(obj, glo- bals=globals(),locals=locals()) 對obj 進行求值,obj 是已編譯為代碼對象的運算式,或是一個字串運算式;可以給出全域或者/和局部的名字空間<br />#exec obj 執行obj、單一的python 語句或者語句的集合,也就是說格式是代碼對象或者字串;obj 也可以是一個檔案對象(已經開啟的有<br />#效python 指令碼中)<br />#input(prompt='') 等同於eval(raw_input(prompt=”))</p><p>### 3.1 callable()<br />#callable()是一個布爾函數,確定一個對象是否可以通過函數操作符(())來調用。如果函數可調用便返回True,否則便是False.<br />#print(callable(dir))<br />#print(callable(1))<br />#--><br />#True<br />#False</p><p>### 3.2 compile()<br />#compile()函數允許程式員在運行時刻迅速產生代碼對象,然後就可以用exec 語句或者內建函<br />#數eval()來執行這些對象或者對它們進行求值。一個很重要的觀點是:exec 和eval()都可以執行字<br />#符串格式的Python 代碼。當執行字串形式的代碼時,每次都必須對這些代碼進行位元組編譯處理。<br />#compile()函數提供了一次性位元組代碼先行編譯,以後每次調用的時候,都不用編譯了</p><p>#compile 的三個參數都是必需的,第一參數代表了要編譯的python 代碼。第二個字串,雖然<br />#是必需的,但通常被置為空白串。該參數代表了存放代碼對象的檔案的名字(字串類型)。compile 的<br />#通常用法是動態產生字串形式的Python 代碼, 然後產生一個代碼對象——代碼顯然沒有存放在任何檔案。<br />#<br />#最後的參數是個字串,它用來表明代碼對象的類型。有三個可能值:<br />#'eval' 可求值的運算式[和eval()一起使用]<br />#'single' 單一可執行語句[和exec 一起使用]<br />#'exec' 可執行語句組[和exec 一起使用]</p><p>#可求值運算式<br />#eval_code = compile('100 + 200', '', 'eval')<br />#print(eval(eval_code))<br />#--><br />#300</p><p>#單一可執行語句<br />#single_code = compile('print("Hello world!")', '', 'single')<br />#print(single_code)<br />#exec(single_code)<br />#--><br />#<code object <module> at 0x0000000002275718, file "", line 1><br />#Hello world!</p><p>#可執行語句組<br />#exec_code = compile("""<br />#req = input('Count how many numbers? ')<br />#for eachNum in range(int(req)):<br /># print(eachNum)<br />#""", '', 'exec')<br />#exec(exec_code)<br />#--><br />#Count how many numbers? 4<br />#0<br />#1<br />#2<br />#3</p><p>## 3.3 eval()<br />#eval()對錶達式求值,後者可以為字串或內建函數complie()建立的先行編譯代碼對象。這是<br />#eval()第一個也是最重要的參數。第二個和第三個參數,都為可選的,分別代表了全域和局部名字空間中的對象。<br />#如果給出這兩個參數,globals 必須是個字典,locals可以是任意的映射對象,比如,一個實現了__getitem__()方法的對象。<br />#如果都沒給出這兩個參數,分別預設為globals()和locals()返回的對象,如果只傳入了一個全域字典,那麼該字典也作為locals 傳入。</p><p>#print(eval('932'))<br />#932<br />#print(int('932'))<br />#932<br />#<br /># 在這種情況下,eval()和int()都返回相同的結果:整數932。然而,它們採用的方式卻不盡相<br />#同。內建函數eval()接收引號內的字串並把它作為python 運算式進行求值。內建函數int()接收<br />#代表整數的字串並把它轉換為整數。這隻有在該字串只由字串932 組成的時候才會成功,而<br />#該字串作為運算式傳回值932,932 也是字串”932”所代表的整數。當我們用純字串運算式<br />#的時候,兩者便不再相同了:<br />#print(eval('100 + 200'))<br />#300<br />#print(int('100 + 200'))<br />#ValueError: invalid literal for int(): 100 + 200</p><p>## 3.4 exec</p><p>#和eval()相似,exec 語句執行代碼對象或字串形式的python 代碼。類似地,用compile()<br />#先行編譯重複代碼有助於改善效能,因為在調用時不必經過位元組編譯處理。exec 語句只接受一個參數,<br />#下面便是它的通用文法:<br />#exec obj</p><p>#被執行的對象(obj)可以只是原始的字串,比如單一語句或是語句組,它們也可以先行編譯成<br />#一個代碼對象(分別用'single'和'exec"參數)</p><p>#exec_code = compile("""<br />#req = input('Count how many numbers? ')<br />#for eachNum in range(int(req)):<br /># print(eachNum)<br />#""", '', 'exec')<br />#exec(exec_code)</p><p>## 3.5 input()<br />#內建函數input()是eval()和raw_input()的組合,等價於eval(raw_input())。類似於<br />#raw_input(),input()有一個可選的參數,該參數代表了給使用者的字串提示。如果不給定參數的<br />#話,該字串預設為空白串。<br />#從功能上看,input 不同於raw_input(),因為raw_input()總是以字串的形式,逐字地返回用<br />#戶的輸入。input()履行相同的的任務;而且,它還把輸入作為python 運算式進行求值。這意味著<br />#input()返回的資料是對輸入運算式求值的結果:一個python 對象。</p><p>##************ Part 4: 執行其他(非Python)程式 *****************<br />#在python 程式裡我們也可以執行非python 程式。這些程式包括了二進位可執行檔,其他的<br />#shell 指令碼等等。所有的要求只是一個有效執行環境,比如,允許檔案訪問和執行,指令檔必須<br />#能訪問它們的解譯器(perl, bash,等等),二進位必須是可訪問的(和本地機器的構架相容)</p><p>#執行外部程式的os 模組函數(u 只對unix 有效, w 只對windows 有效)<br />#os 模組函數 描述<br />#system(cmd) 執行程式cmd(字串),等待程式結束,返回結束代碼(windows 下,始終為0)<br />#fork() 建立一個和父進程並行的子進程[通常來說和exec*()一起使用];返回兩次....一次給父進程一次給子進程<br />#execl(file, arg0,arg1,...) 用參數列表arg0, arg1 等等執行檔案<br />#execv(file, arglist) 除了使用參數向量列表,其他的和execl()相同<br />#execle(file, arg0,arg1,... env) 和execl 相同,但提供了環境變數字典env<br />#execve(file,arglist, env) 除了帶有參數向量列表,其他的和execle()相同<br />#execlp(cmd, arg0,arg1,...) 於execl()相同,但是在使用者的搜尋路徑下搜尋完全的檔案路徑名<br />#execvp(cmd, arglist) 除了帶有參數向量列表,與execlp()相同<br />#<br />#execlpe(cmd, arg0, arg1,... env) 和execlp 相同,但提供了環境變數字典env<br />#execvpe(cmd,arglist, env) 和execvp 相同,但提供了環境變數字典env<br />#spawn*a(mode, file, args[, env]) spawn*()家族在一個新的進程中執行路徑,args 作為參數,也許還有環境變數的字典env;模式(mode)是<br />#個顯示不同操作模式的魔術。<br />#wait() 等待子進程完成[通常和fock 和exec*()一起使用] ○U<br />#waitpid(pid,options) 等待指定的子進程完成[通常和fock 和exec*()一起使用] ○U<br />#popen(cmd, mode='r',buffering=-1) 執行字串cmd,返回一個類檔案對象作為運行程式通訊控制代碼,預設為讀模數式和預設系統緩衝<br />#startfileb(path) 用相關 App程式執行路徑 W</p><p>## 4.1 os.system()<br />#system(),一個非常簡單的函數,接收字串形式的系統命令並執行它。當執行命令的時候,python 的運行是掛起的。<br />#當我們的執行完成之後,將會以system()的傳回值形式給出退出狀態,python 的執行也會繼續。</p><p>#system()保留了現有的標準檔案,包括標準的輸出,意味著執行任何的命令和程式顯示輸出都<br />#會傳到標準輸出上。這裡要當心,因為特定應用程式比如公用網關介面(CGI),如果將除了有效超<br />#文本標示語言(HTML)字串之外的輸出,經過標準輸出發送回用戶端,會引起網頁瀏覽器錯誤。<br />#system()通常和不會產生輸出的命令一起使用,其中的一些命令包括了壓縮或轉換檔的程式,掛<br />#載磁碟到系統的程式,或其他執行特定任務的命令---通過退出狀態顯示成功或失敗而不是通過輸入<br />#和/或輸出通訊。通常的約定是利用退出狀態,0 表示成功,非零表示其他類型的錯誤。</p><p>#import os<br />#result = os.system('uname -a')<br />#print(result)</p><p>## 4.2 os.popen()<br />#popen()函數是檔案對象和system()函數的結合。它工作方式和system()相同,但它可以建立<br />#一個指向那個程式的單向串連,然後如訪問檔案一樣訪問這個程式。如果程式要求輸入,那麼你要<br />#用'w'模式寫入那個命令來調用popen()。你發送給程式的資料會通過標準輸入接收到。同樣地,'r'<br />#模式允許spawn 命令,那麼當它寫入標準輸出的時候,你就可以通過類檔案控制代碼使用熟悉的file 對<br />#象的read*()方法來讀取輸入。就像對於檔案,當使用完畢以後,你應當close()串連。</p><p>#import os<br />#f = os.popen('uname -a')<br />#data = f.readline()<br />#f.close()<br />#print(data)</p><p>##************ Part 5: 結束執行 *****************<br />#當程式運行完成,所有模組最進階的語句執行完畢後退出,我們便稱這是乾淨的執行。可能有<br />#很多情況,需要從python 提前退出,比如某種致命錯誤,或是不滿足繼續執行的條件的時候。<br />#在python 中,有各種應對錯誤的方法。其中之一便是通過異常和異常處理。另外一個方法便是<br />#建造一個“清掃器”方法,這樣便可以把代碼的主要部分放在if 語句裡,在沒有錯誤的情況下執行,<br />#因而可以讓錯誤的情況“正常地“終結。然而,有時也需要在退出調用程式的時候,返回錯誤碼<br />#以表明發生何種事件。</p><p>## 5.1 sys.exit() and SystemExit<br />#立即退出程式並返回調用程式的主要方式是sys 模組中的exit()函數。sys.exit()的文法為:<br /># sys.exit(status=0)<br />#當調用sys.exit()時,就會引發systemExit()異常。除非對異常進行監控(在一個try 語句和<br />#合適的except 子句中),異常通常是不會被捕捉到或處理的,解譯器會用給定的狀態參數退出,如<br />#果沒有給出的話,該參數預設為0。System Exit 是唯一不看作錯誤的異常。它僅僅表示要退出python<br />#的願望。</p><p>#sys.exit()經常用在命令調用的中途發現錯誤之後,比如,如果參數不正確,無效,或者參數數目不正確。</p><p>## 5.2 sys.exitfunc()<br />#sys.exitfunc()預設是停用,但你可以改寫它以提供額外的功能。當調用了sys.exit()並<br />#在解譯器退出之前,就會用到這個函數了。這個函數不帶任何參數的,所以你建立的函數也應該是<br />#無參的。<br />#如果sys.exitfunc 已經被先前定義的exit 函數覆蓋了,最好的方法是把這段代碼作為你exit()<br />#函數的一部分來執行。一般說來,exit 函數用於執行某些類型的關閉活動,比如關閉檔案和網路連<br />#接,最好用於完成維護任務,比如釋放先前保留的系統資源。</p><p>## 5.3 os._exit()和 os._exit() 函數<br />#os 模組的_exit()函數不應該在一般應用中使用。(平台相關,只適用特定的平台,比如基於Unix<br />#的平台,以及Win32 平台)。其文法為:<br />#os._exit(status)<br />#這個函數提供的功能與sys.exit()和sys.exitfunc()相反,根本不執行任何清理便立即退出<br />#python。與sys.exit()不同,狀態參數是必需的。通過sys.exit()退出是退出解譯器的首選方法。</p><p>## 5.4 os.kill()<br />#os 模組的kill()函數類比傳統的unix 函數來發送訊號給進程。kill()參數是進程標識數(PID)<br />#和你想要發送到進程的訊號。發送的典型訊號為SIGINT, SIGQUIT,或更徹底地,SIGKILL,來使進程終結。</p><p>

-------------------------------------------------------------------------------------------------------
Blog: http://blog.csdn.net/tianlesoftware 
Weibo: http://weibo.com/tianlesoftware
Email: dvd.dba@gmail.com
DBA1 群:62697716(滿);   DBA2 群:62697977(滿)   DBA3 群:62697850(滿)   
DBA 超級群:63306533(滿);  DBA4 群: 83829929(滿)  DBA5群: 142216823(滿)  
DBA6 群:158654907(滿)   DBA7 群:69087192(滿)   DBA8 群:172855474
DBA 超級群2:151508914  DBA9群:102954821      聊天 群:40132017(滿)
--加群需要在備忘說明Oracle資料表空間和資料檔案的關係,否則拒絕申請

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.