python面試題_第1頁
python面試題_第2頁
python面試題_第3頁
python面試題_第4頁
python面試題_第5頁
已閱讀5頁,還剩90頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Python語言特性1 Python的函數參數傳遞看兩個如下例子,分析運行結果:代碼一:a = 1def fun(a): a = 2fun(a)print(a) # 1代碼二:a = def fun(a):a.append(1)fun(a)print(a) # 1所有的變量都可以理解是內存中一個對象的“引用”,或者,也可以看似c中void*的感覺。這里記住的是類型是屬于對象的,而不是變量。而對象有兩種,“可更改”(mutable)與“不可更改”(immutable)對象。在python中,strings, tuples, 和numbers是不可更改的對象,而list,dict等則是可以修改的對

2、象。(這就是這個問題的重點)當一個引用傳遞給函數的時候,函數自動復制一份引用,這個函數里的引用和外邊的引用沒有半毛關系了.所以第一個例子里函數把引用指向了一個不可變對象,當函數返回的時候,外面的引用沒半毛感覺.而第二個例子就不一樣了,函數內的引用指向的是可變對象,對它的操作就和定位了指針地址一樣,在內存里進行修改.2 Python中的元類(metaclass)元類就是用來創建類的“東西”。你創建類就是為了創建類的實例對象,但是我們已經學習到了Python中的類也是對象。好吧,元類就是用來創建這些類(對象)的,元類就是類的類這個非常的不常用,詳情請看:深刻理解Python中的元類(metacla

3、ss)3 staticmethod和classmethodPython其實有3個方法,即靜態方法(staticmethod),類方法(classmethod)和實例方法,如下: class A(object):    def foo(self,x):        print "executing foo(%s,%s)"%(self,x)     classmethod  &#

4、160; def class_foo(cls,x):        print( "executing class_foo(%s,%s)"%(cls,x)     staticmethod    def static_foo(x):        print ("executing static_foo(%s

5、)"%x) a=A()這里先理解下函數參數里面的self和cls.這個self和cls是對類或者實例的綁定.對于實例方法,我們知道在類里每次定義方法的時候都需要綁定這個實例,就是foo(self, x),為什么要這么做呢?因為實例方法的調用離不開實例,我們需要把實例自己傳給函數,調用的時候是這樣的a.foo(x)(其實是foo(a, x).類方法一樣,只不過它傳遞的是類而不是實例,A.class_foo(x).注意這里的self和cls可以替換別的參數,但是python的約定是這倆,還是不要改的好.對于靜態方法其實和普通的方法一樣,不需要對誰進行綁定,唯一的區別是調用的時候

6、需要使用a.static_foo(x)或者A.static_foo(x)來調用.實例方法類方法靜態方法a = A()a.foo(x)a.class_foo(x)a.static_foo(x)A不可用A.class_foo(x)A.static_foo(x)4 類變量和實例變量class Person:    name="aaa" p1=Person()p2=Person()="bbb"print()  # bbbprint() 

7、60;# aaaprint(P)  # aaa類變量就是供類使用的變量,實例變量就是供實例使用的.這里="bbb"是實例調用了類變量,這其實和上面第一個問題一樣,就是函數傳參的問題,一開始是指向的類變量name="aaa",但是在實例的作用域里把類變量的引用改變了,就變成了一個實例變量,不再引用Person的類變量name了.可以看看下面的例子:class Person:    name= p1=Person()p2=P

8、erson().append(1)print()  # 1print()  # 1print(P)  # 15 Python自省這個也是python彪悍的特性.自省就是面向對象的語言所寫的程序在運行時,所能知道對象的類型.簡單一句就是運行時能夠獲得對象的類型.比如type(),dir(),getattr(),hasattr(),isinstance().6 字典推導式可能你見過列表推導時,卻沒有見過字典推導式,在2.7中才加入的:d = key: value for (ke

9、y, value) in iterable7 Python中單下劃線和雙下劃線1234567891011121314>>> class MyClass():.     def _init_(self):.             self._superprivate = "Hello".         

10、60;   self._semiprivate = ", world!".>>> mc = MyClass()>>> print(mc._superprivate)Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: myClass instance has no attribute '_superprivate'>

11、>> print(mc._semiprivate), world!>>> print mc._dict_'_MyClass_superprivate': 'Hello', '_semiprivate': ', world!'_foo_:一種約定,Python內部的名字,用來區別其他用戶自定義的命名,以防沖突._foo:一種約定,用來指定變量私有.程序員用來指定私有變量的一種方式._foo:這個有真正的意義:解析器用_classname_foo來代替這個名字,以區別和其他類相同的命名.詳情見:8 字符串

12、格式化:%和.format.format在許多方面看起來更便利.對于%最煩人的是它無法同時傳遞一個變量和元組.你可能會想下面的代碼不會有什么問題:Python:"hi there %s" % name但是,如果name恰好是(1,2,3),它將會拋出一個TypeError異常.為了保證它總是正確的,你必須這樣做:"hi there %s" % (name,)   # 提供一個單元素的數組而不是一個參數9 迭代器和生成器在Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。可以被next()函數調用并不斷返回下一

13、個值的對象稱為迭代器:Iterator。這個是stackoverflow里python排名第一的問題,值得一看: 10 *args and *kwargs用*args和*kwargs只是為了方便并沒有強制使用它們.當你不確定你的函數里將要傳遞多少參數時你可以用*args.例如,它可以傳遞任意數量的參數:12345678>>> def print_everything(*args):        for count, thing in enumerate(args):

14、.         print '0. 1'.format(count, thing).>>> print_everything('apple', 'banana', 'cabbage')0. apple1. banana2. cabbage相似的,*kwargs允許你使用沒有事先定義的參數名:1234567>>> def table_things(*kwargs):.    

15、 for name, value in kwargs.items():.         print '0 = 1'.format(name, value).>>> table_things(apple = 'fruit', cabbage = 'vegetable')cabbage = vegetableapple = fruit你也可以混著用.命名參數首先獲得參數值然后所有的其他參數都傳遞給*args和*kwargs.命名參數在列表的最前端.例如

16、:1def table_things(titlestring, *kwargs)*args和*kwargs可以同時在函數的定義中,但是*args必須在*kwargs前面.當調用函數時你也可以用*和*語法.例如:1234567>>> def print_three_things(a, b, c):.     print 'a = 0, b = 1, c = 2'.format(a,b,c).>>> mylist = 'aardvark', 'baboon', 'ca

17、t'>>> print_three_things(*mylist) a = aardvark, b = baboon, c = cat就像你看到的一樣,它可以傳遞列表(或者元組)的每一項并把它們解包.注意必須與它們在函數里的參數相吻合.當然,你也可以在函數定義或者函數調用時用*.11 面向切面編程AOP和裝飾器這個AOP一聽起來有點懵,同學面試的時候就被問懵了裝飾器是一個很著名的設計模式,經常被用于有切面需求的場景,較為經典的有插入日志、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼并

18、繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。這個問題比較大,推薦: 12 鴨子類型“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。”我們并不關心對象是什么類型,到底是不是鴨子,只關心行為。比如在python中,有很多file-like的東西,比如StringIO,GzipFile,socket。它們有很多相同的方法,我們把它們當作文件使用。又比如list.extend()方法中,我們并不關心它的參數是不是list,只要它是可迭代的,所以它的參數可以是list/tuple/dict/字符串/生成器等.鴨子類型在動態語言中經常使用,非

19、常靈活,使得python不想java那樣專門去弄一大堆的設計模式。13 Python中重載函數重載主要是為了解決兩個問題。1. 可變參數類型。2. 可變參數個數。另外,一個基本的設計原則是,僅僅當兩個函數除了參數類型和參數個數不同以外,其功能是完全相同的,此時才使用函數重載,如果兩個函數的功能其實不同,那么不應當使用重載,而應當使用一個名字不同的函數。好吧,那么對于情況 1 ,函數功能相同,但是參數類型不同,python 如何處理?答案是根本不需要處理,因為 python 可以接受任何類型的參數,如果函數的功能相同,那么不同的參數類型在 python 中很可能是相同的代碼,沒有必要做成兩個不同

20、函數。那么對于情況 2 ,函數功能相同,但參數個數不同,python 如何處理?大家知道,答案就是缺省參數。對那些缺少的參數設定為缺省參數即可解決問題。因為你假設函數功能相同,那么那些缺少的參數終歸是需要用的。好了,鑒于情況 1 跟 情況 2 都有了解決方案,python 自然就不需要函數重載了。14 新式類和舊式類這個面試官問了,我說了老半天,不知道他問的真正意圖是什么.新式類很早在2.2就出現了,所以舊式類完全是兼容的問題,Python3里的類全部都是新式類.這里有一個MRO問題可以了解下(新式類是廣度優先,舊式類是深度優先),<Python核心編程>里講的也很多.15

21、0;_new_和_init_的區別這個_new_確實很少見到,先做了解吧.1. _new_是一個靜態方法,而_init_是一個實例方法.2. _new_方法會返回一個創建的實例,而_init_什么都不返回.3. 只有在_new_返回一個cls的實例時后面的_init_才能被調用.4. 當創建一個新實例時調用_new_,初始化一個實例時用_init_.ps: _metaclass_是創建類時起作用.所以我們可以分別使用_metaclass_,_new_和_init_來分別在類創建,實例創建和實例初始化的時候做一些小手腳.16 單例模式這個絕對常考啊.絕對要記住12個方法,當時面試官是讓

22、手寫的.1 使用_new_方法class Singleton(object):    def _new_(cls, *args, *kw):        if not hasattr(cls, '_instance'):            orig = super(Singleton, cls)   

23、60;        cls._instance = orig._new_(cls, *args, *kw)        return cls._instance class MyClass(Singleton):    a = 12 共享屬性創建實例時把所有實例的_dict_指向同一個字典,這樣它們具有相同的屬性和方法.123456789class Borg(object):

24、0;   _state =     def _new_(cls, *args, *kw):        ob = super(Borg, cls)._new_(cls, *args, *kw)        ob._dict_ = cls._state        return ob&

25、#160;class MyClass2(Borg):    a = 13 裝飾器版本1234567891011def singleton(cls, *args, *kw):    instances =     def getinstance():        if cls not in instances:       &#

26、160;    instancescls = cls(*args, *kw)        return instancescls    return getinstance singletonclass MyClass:4 import方法作為python的模塊是天然的單例模式# mysingleton.pyclass My_Singleton(object):    def foo(

27、self):        pass my_singleton = My_Singleton() # to usefrom mysingleton import my_singleton my_singleton.foo()17 Python中的作用域Python 中,一個變量的作用域總是由在代碼中被賦值的地方所決定的。當 Python 遇到一個變量的話他會按照這樣的順序進行搜索:本地作用域(Local)當前作用域被嵌入的本地作用域(Enclosing locals)全局/模塊作用域(

28、Global)內置作用域(Built-in)18 GIL線程全局鎖線程全局鎖(Global Interpreter Lock),即Python為了保證線程安全而采取的獨立線程運行的限制,說白了就是一個核只能在同一時間運行一個線程.解決辦法就是多進程和下面的協程(協程也只是單CPU,但是能減小切換代價提升性能).19 協程簡單點說協程是進程和線程的升級版,進程和線程都面臨著內核態和用戶態的切換問題而耗費許多切換時間,而協程就是用戶自己控制切換的時機,不再需要陷入系統的內核態.Python里最常見的yield就是協程的思想!可以查看第九個問題.20 閉包閉包(closure)是函數式編程的重要的語

29、法結構。閉包也是一種組織代碼的結構,它同樣提高了代碼的可重復使用性。當一個內嵌函數引用其外部作作用域的變量,我們就會得到一個閉包. 總結一下,創建一個閉包必須滿足以下幾點:1. 必須有一個內嵌函數2. 內嵌函數必須引用外部函數中的變量3. 外部函數的返回值必須是內嵌函數感覺閉包還是有難度的,幾句話是說不明白的,還是查查相關資料.重點是函數運行后并不會被撤銷,就像16題的instance字典一樣,當函數運行完后,instance并不被銷毀,而是繼續留在內存空間里.這個功能類似類里的類變量,只不過遷移到了函數上.閉包就像個空心球一樣,你知道外面和里面,但你不知道中間是什么樣.21 lambda函數

30、其實就是一個匿名函數,為什么叫lambda?因為和后面的函數式編程有關.22 Python函數式編程這個需要適當的了解一下吧,畢竟函數式編程在Python中也做了引用.python中函數式編程支持:filter 函數的功能相當于過濾器。調用一個布爾函數bool_func來迭代遍歷每個seq中的元素;返回一個使bool_seq返回值為true的元素的序列。>>>a = 1,2,3,4,5,6,7>>>b = filter(lambda x: x > 5, a)>>>print b>>>6,7map函數是對一個序列的每個

31、項依次執行函數,下面是對一個序列每個項都乘以2:>>> a = map(lambda x:x*2,1,2,3)>>> list(a)2, 4, 6reduce函數是對一個序列的每個項迭代調用函數,下面是求3的階乘:>>> reduce(lambda x,y:x*y,range(1,4)623 Python里的拷貝引用和copy(),deepcopy()的區別1234567891011121314151617181920import copya = 1, 2, 3, 4, 'a', 'b'  

32、;#原始對象 b = a  #賦值,傳對象的引用c = copy.copy(a)  #對象拷貝,淺拷貝d = copy.deepcopy(a)  #對象拷貝,深拷貝 a.append(5)  #修改對象aa4.append('c')  #修改對象a中的'a', 'b'數組對象 print 'a = ', aprint 'b = ', bprint 'c = ', cpri

33、nt 'd = ', d 輸出結果:a =  1, 2, 3, 4, 'a', 'b', 'c', 5b =  1, 2, 3, 4, 'a', 'b', 'c', 5c =  1, 2, 3, 4, 'a', 'b', 'c'd =  1, 2, 3, 4, 'a', 'b'24 Python垃圾回收機制Pytho

34、n GC主要使用引用計數(reference counting)來跟蹤和回收垃圾。在引用計數的基礎上,通過“標記-清除”(mark and sweep)解決容器對象可能產生的循環引用問題,通過“分代回收”(generation collection)以空間換時間的方法提高垃圾回收效率。1 引用計數PyObject是每個對象必有的內容,其中ob_refcnt就是做為引用計數。當一個對象有新的引用時,它的ob_refcnt就會增加,當引用它的對象被刪除,它的ob_refcnt就會減少.引用計數為0時,該對象生命就結束了。優點:1. 簡單2. 實時性缺點:1. 維護引用計數消耗資源2. 循環引用2

35、標記-清除機制基本思路是先按需分配,等到沒有空閑內存的時候從寄存器和程序棧上的引用出發,遍歷以對象為節點、以引用為邊構成的圖,把所有可以訪問到的對象打上標記,然后清掃一遍內存空間,把所有沒標記的對象釋放。3 分代技術分代回收的整體思想是:將系統中的所有內存塊根據其存活時間劃分為不同的集合,每個集合就成為一個“代”,垃圾收集頻率隨著“代”的存活時間的增大而減小,存活時間通常利用經過幾次垃圾回收來度量。Python默認定義了三代對象集合,索引數越大,對象存活時間越長。舉例:當某些內存塊M經過了3次垃圾收集的清洗之后還存活時,我們就將內存塊M劃到一個集合A中去,而新分配的內存都劃分到集合B中去。當垃

36、圾收集開始工作時,大多數情況都只對集合B進行垃圾回收,而對集合A進行垃圾回收要隔相當長一段時間后才進行,這就使得垃圾收集機制需要處理的內存少了,效率自然就提高了。在這個過程中,集合B中的某些內存塊由于存活時間長而會被轉移到集合A中,當然,集合A中實際上也存在一些垃圾,這些垃圾的回收會因為這種分代的機制而被延遲。25 Python里面如何實現tuple和list的轉換?答:tuple,可以說是不可變的list,訪問方式還是通過索引下標的方式。當你明確定義個tuple是,如果僅有一個元素,必須帶有,例如:(1,)。當然,在2.7以后的版,python里還增加了命名式的tuple!至于有什么用,首先

37、第一點,樓主玩過python都知道,python的函數可以有多返回值的,而python里,多返回值,就是用tuple來表示,這是用的最廣的了,比如說,你需要定義一個常量的列表,但你又不想使用list,那也可以是要你管tuple,例如:if a in ('A','B','C'):pass26 Python的isis是對比地址,=是對比值27 read,readline和readlines· read 讀取整個文件· readline 讀取下一行,使用生成器方法· readlines 讀取整個文件到一個迭代器以供我們遍歷

38、28 Python2和3的區別大部分Python庫都同時支持Python 2.7.x和3.x版本的,所以不論選擇哪個版本都是可以的。但為了在使用Python時避開某些版本中一些常見的陷阱,或需要移植某個Python項目使用_future_模塊print函數整數除法Unicodexrange觸發異常處理異常next()函數和.next()方法For循環變量與全局命名空間泄漏比較無序類型使用input()解析輸入內容返回可迭代對象,而不是列表推薦:Python 2.7.x 和 3.x 版本的重要區別29到底什么是Python?你可以在回答中與其他技術進行對比答案下面是一些關鍵點:· Py

39、thon是一種解釋型語言。這就是說,與C語言和C的衍生語言不同,Python代碼在運行之前不需要編譯。其他解釋型語言還包括PHP和Ruby。· Python是動態類型語言,指的是你在聲明變量時,不需要說明變量的類型。你可以直接編寫類似x=111和x="I'm a string"這樣的代碼,程序不會報錯。· Python非常適合面向對象的編程(OOP),因為它支持通過組合(composition)與繼承(inheritance)的方式定義類(class)。Python中沒有訪問說明符(access specifier,類似C+中的public和pr

40、ivate),這么設計的依據是“大家都是成年人了”。· 在Python語言中,函數是第一類對象(first-class objects)。這指的是它們可以被指定給變量,函數既能返回函數類型,也可以接受函數作為輸入。類(class)也是第一類對象。· Python代碼編寫快,但是運行速度比編譯語言通常要慢。好在Python允許加入基于C語言編寫的擴展,因此我們能夠優化代碼,消除瓶頸,這點通常是可以實現的。numpy就是一個很好地例子,它的運行速度真的非常快,因為很多算術運算其實并不是通過Python實現的。· Python用途非常廣泛網絡應用,自動化,科學建模,大數

41、據應用,等等。它也常被用作“膠水語言”,幫助其他語言和組件改善運行狀況。· Python讓困難的事情變得容易,因此程序員可以專注于算法和數據結構的設計,而不用處理底層的細節。為什么提這個問題:如果你應聘的是一個Python開發崗位,你就應該知道這是門什么樣的語言,以及它為什么這么酷。以及它哪里不好。30補充缺失的代碼def print_directory_contents(sPath): """ 這個函數接受文件夾的名稱作為輸入參數, 返回該文件夾中文件的路徑, 以及其包含文件夾中文件的路徑。 """ # 補充代碼答案def

42、 print_directory_contents(sPath): import os for sChild in os.listdir(sPath): sChildPath = os.path.join(sPath,sChild) if os.path.isdir(sChildPath): print_directory_contents(sChildPath) else: print sChildPath特別要注意以下幾點:· 命名規范要統一。如果樣本代碼中能夠看出命名規范,遵循其已有的規范。· 遞歸函數需要遞歸并終止。確保你明白其中的原理,否則你將面臨無休無止的調用棧

43、(callstack)。· 我們使用os模塊與操作系統進行交互,同時做到交互方式是可以跨平臺的。你可以把代碼寫成sChildPath = sPath + '/' + sChild,但是這個在Windows系統上會出錯。· 熟悉基礎模塊是非常有價值的,但是別想破腦袋都背下來,記住Google是你工作中的良師益友。· 如果你不明白代碼的預期功能,就大膽提問。· 堅持KISS原則!保持簡單,不過腦子就能懂!為什么提這個問題:· 說明面試者對與操作系統交互的基礎知識· 遞歸真是太好用啦31閱讀下面的代碼,寫出A0,A1至An的

44、最終值。A0 = dict(zip('a','b','c','d','e'),(1,2,3,4,5)A1 = range(10)A2 = i for i in A1 if i in A0A3 = A0s for s in A0A4 = i for i in A1 if i in A3A5 = i:i*i for i in A1A6 = i,i*i for i in A1答案A0 = 'a': 1, 'c': 3, 'b': 2, 'e': 5, 

45、9;d': 4A1 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9A2 = A3 = 1, 3, 2, 5, 4A4 = 1, 2, 3, 4, 5A5 = 0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81A6 = 0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81為什么提這個問題:· 列表解析(list comprehension)十分節約時間,對很多人來說也是一個大的學習障礙。· 如果你讀懂了

46、這些代碼,就很可能可以寫下正確地值。· 其中部分代碼故意寫的怪怪的。因為你共事的人之中也會有怪人。32下面代碼會輸出什么:def f(x,l=): for i in range(x): l.append(i*i) print(l)f(2)f(3,3,2,1)f(3)答案:0, 13, 2, 1, 0, 1, 40, 1, 0, 1, 4呃?第一個函數調用十分明顯,for循環先后將0和1添加至了空列表l中。l是變量的名字,指向內存中存儲的一個列表。第二個函數調用在一塊新的內存中創建了新的列表。l這時指向了新生成的列表。之后再往新列表中添加0、1和4。很棒吧。第三個函數調用的結果就有些奇

47、怪了。它使用了之前內存地址中存儲的舊列表。這就是為什么它的前兩個元素是0和1了。33你如何管理不同版本的代碼?答案:版本管理!被問到這個問題的時候,你應該要表現得很興奮,甚至告訴他們你是如何使用Git(或是其他你最喜歡的工具)追蹤自己和奶奶的書信往來。我偏向于使用Git作為版本控制系統(VCS),但還有其他的選擇,比如subversion(SVN)。為什么提這個問題:因為沒有版本控制的代碼,就像沒有杯子的咖啡。有時候我們需要寫一些一次性的、可以隨手扔掉的腳本,這種情況下不作版本控制沒關系。但是如果你面對的是大量的代碼,使用版本控制系統是有利的。版本控制能夠幫你追蹤誰對代碼庫做了什么操作;發現新

48、引入了什么bug;管理你的軟件的不同版本和發行版;在團隊成員中分享源代碼;部署及其他自動化處理。它能讓你回滾到出現問題之前的版本,單憑這點就特別棒了。還有其他的好功能。怎么一個棒字了得!34“猴子補丁”(monkey patching)指的是什么?這種做法好嗎?答案:“猴子補丁”就是指,在函數或對象已經定義之后,再去改變它們的行為。舉個例子:import datetimedatetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)大部分情況下,這是種很不好的做法 - 因為函數在代碼庫中的行為最好是都保持一致。打“猴子補丁”的原因

49、可能是為了測試。mock包對實現這個目的很有幫助。為什么提這個問題?答對這個問題說明你對單元測試的方法有一定了解。你如果提到要避免“猴子補丁”,可以說明你不是那種喜歡花里胡哨代碼的程序員(公司里就有這種人,跟他們共事真是糟糕透了),而是更注重可維護性。還記得KISS原則碼?答對這個問題還說明你明白一些Python底層運作的方式,函數實際是如何存儲、調用等等。另外:如果你沒讀過mock模塊的話,真的值得花時間讀一讀。這個模塊非常有用。35閱讀下面的代碼,它的輸出結果是什么?class A(object): def go(self): print "go A go!" def

50、stop(self): print "stop A stop!" def pause(self): raise Exception("Not Implemented")class B(A): def go(self): super(B, self).go() print "go B go!"class C(A): def go(self): super(C, self).go() print "go C go!" def stop(self): super(C, self).stop() print "s

51、top C stop!"class D(B,C): def go(self): super(D, self).go() print "go D go!" def stop(self): super(D, self).stop() print "stop D stop!" def pause(self): print "wait D wait!"class E(B,C): passa = A()b = B()c = C()d = D()e = E()# 說明下列代碼的輸出結果a.go()b.go()c.go()d.go()e.

52、go()a.stop()b.stop()c.stop()d.stop()e.stop()a.pause()b.pause()c.pause()d.pause()e.pause()答案輸出結果以注釋的形式表示:a.go()# go A go!b.go()# go A go!# go B go!c.go()# go A go!# go C go!d.go()# go A go!# go C go!# go B go!# go D go!e.go()# go A go!# go C go!# go B go!a.stop()# stop A stop!b.stop()# stop A stop!c.

53、stop()# stop A stop!# stop C stop!d.stop()# stop A stop!# stop C stop!# stop D stop!e.stop()# stop A stop!a.pause()# . Exception: Not Implementedb.pause()# . Exception: Not Implementedc.pause()# . Exception: Not Implementedd.pause()# wait D wait!e.pause()# .Exception: Not Implemented為什么提這個問題?因為面向對象的

54、編程真的真的很重要。不騙你。答對這道問題說明你理解了繼承和Python中super函數的用法。36閱讀下面的代碼,它的輸出結果是什么?class Node(object): def _init_(self,sName): self._lChildren = self.sName = sName def _repr_(self): return "<Node ''>".format(self.sName) def append(self,*args,*kwargs): self._lChildren.append(*args,*kwargs) de

55、f print_all_1(self): print self for oChild in self._lChildren: oChild.print_all_1() def print_all_2(self): def gen(o): lAll = o, while lAll: oNext = lAll.pop(0) lAll.extend(oNext._lChildren) yield oNext for oNode in gen(self): print oNodeoRoot = Node("root")oChild1 = Node("child1"

56、;)oChild2 = Node("child2")oChild3 = Node("child3")oChild4 = Node("child4")oChild5 = Node("child5")oChild6 = Node("child6")oChild7 = Node("child7")oChild8 = Node("child8")oChild9 = Node("child9")oChild10 = Node("chil

57、d10")oRoot.append(oChild1)oRoot.append(oChild2)oRoot.append(oChild3)oChild1.append(oChild4)oChild1.append(oChild5)oChild2.append(oChild6)oChild4.append(oChild7)oChild3.append(oChild8)oChild3.append(oChild9)oChild6.append(oChild10)# 說明下面代碼的輸出結果oRoot.print_all_1()oRoot.print_all_2()答案oRoot.print_

58、all_1()會打印下面的結果:<Node 'root'><Node 'child1'><Node 'child4'><Node 'child7'><Node 'child5'><Node 'child2'><Node 'child6'><Node 'child10'><Node 'child3'><Node 'child8'

59、;><Node 'child9'>oRoot.print_all_1()會打印下面的結果:<Node 'root'><Node 'child1'><Node 'child2'><Node 'child3'><Node 'child4'><Node 'child5'><Node 'child6'><Node 'child8'><Node

60、 'child9'><Node 'child7'><Node 'child10'>為什么提這個問題?因為對象的精髓就在于組合(composition)與對象構造(object construction)。對象需要有組合成分構成,而且得以某種方式初始化。這里也涉及到遞歸和生成器(generator)的使用。生成器是很棒的數據類型。你可以只通過構造一個很長的列表,然后打印列表的內容,就可以取得與print_all_2類似的功能。生成器還有一個好處,就是不用占據很多內存。有一點還值得指出,就是print_all_1會以深度

61、優先(depth-first)的方式遍歷樹(tree),而print_all_2則是寬度優先(width-first)。有時候,一種遍歷方式比另一種更合適。但這要看你的應用的具體情況。36.介紹一下except的用法和作用?答:tryexceptexceptelsefinally執行try下的語句,如果引發異常,則執行過程會跳到except語句。對每個except分支順序嘗試執行,如果引發的異常與except中的異常組匹配,執行相應的語句。如果所有的except都不匹配,則異常會傳遞到下一個調用本代碼的最高層try代碼中。try下的語句正常執行,則執行else塊代碼。如果發生異常,就不會執行如果存在finally語句,最后總是會執行。37.Python中pass語句的作用是什么?答:pass語句不會執行任何操作,一般作為占位符或者創建占位程序,whileFalse:pass38.介紹一下Python下range()函

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論