上海Python2期週考 1 介紹 滿分100分,90分及格 考試範圍: 1.Python基礎 2.數據類型 3.流程控制 4.文件處理 5.函數 6.面向對象 考試時間: 週五下午3:30-4:30筆試 4:30-6:30機試 2 基礎題(40分) 1.什麼是常量?在python中如何定義常量(1分) 2.*args,**kwargs的做用是什麼?如何使用? (3分) 3.python中如何拷貝一個對象?(賦值,淺拷貝,深拷貝的區別)(1分) 4.Python是如何進行bytes和str之間轉換的(1分) 5.Python中re模塊match()和search()的區別(1分) 6.簡要描述Python的垃圾回收機制(garbage collection)(2分) 7.有以下列表,請使用匿名函數按照年齡排序(3分) l=[ {'name':'alex','age':84}, {'name':'oldboy','age':73}, {'name':'egon','age':18}, ] 8.簡述__new__和__init__的區別(1分) 9.多重繼承的執行順序,請解答如下輸出結果是什麼?(4分) class A(object): def __init__(self): print('A') super(A, self).__init__() class B(object): def __init__(self): print('B') super(B, self).__init__() class C(A): def __init__(self): print('C') super(C, self).__init__() class D(A): def __init__(self): print('D') super(D, self).__init__() class E(B, C): def __init__(self): print('E') super(E, self).__init__() class F(C, B, D): def __init__(self): print('F') super(F, self).__init__() class G(D, B): def __init__(self): print('G') super(G, self).__init__() if __name__ == '__main__': g = G() f = F() 10.python中tuple和list的轉換(1分) 11.交換變量三種方式:a=1,b=2(3分) 12.請使用隨機模塊生成4位驗證碼(驗證碼包含數字、小寫字母(65~90爲26個大寫英文字母,97~122號爲26個小寫英文字母))(6分) 13.請回答結果(3分) def extendList(val, list=[]): list.append(val) return list list1 = extendList(10) list2 = extendList(123, []) list3 = extendList('a') print(list1) print(list2) print(list3) 14.Python中如何動態獲取和設置對象的屬性。(1分) 15.下面這段代碼的輸出結果將是什麼?(2分) class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print(Parent.x, Child1.x, Child2.x) Child1.x = 2 print(Parent.x, Child1.x, Child2.x) Parent.x = 3 print(Parent.x, Child1.x, Child2.x) 16.類的屬性和對象的屬性有什麼區別?(1分) 17.什麼是新式類,什麼是經典類,兩者有什麼區別?什麼是深度優先,什麼是廣度優先?(1分) 18.什麼是綁定到對象的方法,、如何定義,如何調用,給誰用?有什麼特性(1分) 19.介紹一下except的用法和做用?(3分) 20.有字符串'email1:378533872@qq.com email2:333312312@163.com eamil3:alexsb123@gmail.com' 匹配出全部的郵箱地址:['378533872@qq.com', '333312312@163.com', 'alexsb123@gmail.com'](1分) 3 綜合題(60分) 考試內容:從零開始編寫選課系統全部功能 •新建項目,整個編程期間,pycharm窗口最大化,不容許切換窗口,再次強調!!!考試期間不容許切換窗口,不容許窗口最小化!!!! •項目中用到的變量名,函數名,文件名,模塊名都須要跟老師的不同,能夠考慮加入本身的名字做爲前綴(很是醜陋,但爲了防止做弊,egon很是拼) •全部功能須要正常運行
2期7月6日答案 1 不變的量或在程序運行過程當中不變的量 python中沒有專門的語法表明常量,約定俗成用變量名全大寫表示 2. *args和**kwargs一般使用在函數定義裏,*args容許函數傳入不定量個數的非關鍵字參數,**kwargs容許函數傳入不定量個數的關鍵字參數 3. 賦值(=),就是建立了對象的一個新的引用,修改其中任意一個變量都會影響到另外一個。 淺拷貝:建立一個新的對象,但它包含的是對原始對象中包含項的引用(若是用引用的方式修改其中一個對象,另一個也會修改改變){1,徹底切片方法;2,工廠函數,如list();3,copy模塊的copy()函數} 深拷貝:建立一個新的對象,而且遞歸的複製它所包含的對象(修改其中一個,另一個不會改變){copy模塊的deep.deepcopy()函數} 4.encode、decode 5. re模塊中match(pattern,string[,flags]),檢查string的開頭是否與pattern匹配。 re模塊中research(pattern,string[,flags]),在string搜索pattern的第一個匹配值。 6. https://www.jianshu.com/p/1e375fb40506 引用計數一旦爲0 就回被回收 7. l.sort(key=lambda item:item['age']) print(l) 8. __init__爲初始化方法,__new__方法是真正的構造函數。 __new__是實例建立以前被調用,它的任務是建立並返回該實例,是靜態方法 __init__是實例建立以後被調用的,而後設置對象屬性的一些初始值。 總結:__new__方法在__init__方法以前被調用,而且__new__方法的返回值將傳遞給__init__方法做爲第一個參數,最後__init__給這個實例設置一些參數。 9. G D A B F C B D A 10.list() tuple() 11. a=1 b=2 #1. 方式一: 引入變量 c=a a=b b=c #2. 方式二: 計算的方式 a = a+b b = a-b a = a-b a +=1 b -= 1 #3. 方式三:交換賦值 a,b=b,a 12. import random def make_code(n): res='' for i in range(n): s1=chr(random.randint(97,122)) s2=str(random.randint(0,9)) res+=random.choice([s1,s2]) return res print(make_code(4)) 13. 形參不能使用可變類型,會重複引用 [10, 'a'] [123] [10, 'a'] 14.setattr、getattr 15. 1 1 1 1 2 1 3 2 3 16. 類的數據屬性是全部對象共享的,id都同樣 類的函數屬性是綁定給對象使用的,obj.method稱爲綁定方法,內存地址都不同 對象的屬性是對象本身獨有的 17. 經典類與新式類 1.只有在python2中才分新式類和經典類,python3中統一都是新式類 2.在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類 3.在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類 3.在python3中,不管是否繼承object,都默認繼承object,即python3中全部類均爲新式類 Python中子類能夠同時繼承多個父類,如A(B,C,D) 若是繼承關係爲非菱形結構,則會按照先找B這一條分支,而後再找C這一條分支,最後找D這一條分支的順序直到找到咱們想要的屬性 若是繼承關係爲菱形結構,那麼屬性的查找方式有兩種,分別是:深度優先和廣度優先 當類是經典類時,多繼承狀況下,在要查找屬性不存在時,會按照深度優先的方式查找下去 當類是新式類時,多繼承狀況下,在要查找屬性不存在時,會按照廣度優先的方式查找下去 python究竟是如何實現繼承的,對於你定義的每個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的全部基類的線性順序列表 F.mro() #等同於F.__mro__ 爲了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類爲止。 而這個MRO列表的構造是經過一個C3線性化算法來實現的。咱們不去深究這個算法的數學原理,它實際上就是合併全部父類的MRO列表並遵循以下三條準則: 1.子類會先於父類被檢查 2.多個父類會根據它們在列表中的順序被檢查 3.若是對下一個類存在兩個合法的選擇,選擇第一個父類 18. 類中定義的函數(沒有被任何裝飾器裝飾的)是類的函數屬性,類可使用,但必須遵循函數的參數規則,有幾個參數須要傳幾個參數 類中定義的函數(沒有被任何裝飾器裝飾的),其實主要是給對象使用的,並且是綁定到對象的,雖然全部對象指向的都是相同的功能,可是綁定到不一樣的對象就是不一樣的綁定方法 強調:綁定到對象的方法的特殊之處在於,綁定給誰就由誰來調用,誰來調用,就會將‘誰’自己當作第一個參數傳給方法,即自動傳值(方法__init__也是同樣的道理) 注意:綁定到對象的方法的這種自動傳值的特徵,決定了在類中定義的函數都要默認寫一個參數self,self能夠是任意名字,可是約定俗成地寫出self。 python中一切皆爲對象,且python3中類與類型是一個概念,類型就是類 19. 執行try下的語句,若是引起異常,則執行過程會跳到except語句。對每一個except分支順序嘗試執行,若是引起的異常與except中的異常組匹配,執行相應的語句。若是全部的except都不匹配,則異常會傳遞到下一個調用本代碼的最高層try代碼中。 20. re.findall(r":(.*?@.*?com)",'email1:378533872@qq.com email2:333312312@163.com eamil3:alexsb123@gmail.com')
(一)、這兩個參數是什麼意思:*args,**kwargs?咱們爲何要使用它們? 答:若是咱們不肯定往一個函數中傳入多少參數,或者咱們但願以元組(tuple)或者列表(list)的形式傳參數的時候,咱們可使用*args(單星號)。若是咱們不知道往函數中傳遞多少個關鍵詞參數或者想傳入字典的值做爲關鍵詞參數的時候咱們可使用**kwargs(雙星號),args、kwargs兩個標識符是約定俗成的用法。 另外一種答法:當函數的參數前面有一個星號*號的時候表示這是一個可變的位置參數,兩個星號**表示這個是一個可變的關鍵詞參數。星號*把序列或者集合解包(unpack)成位置參數,兩個星號**把字典解包成關鍵詞參數。 (二)、談一談Python的裝飾器(decorator) 裝飾器本質上是一個Python函數,它可讓其它函數在不做任何變更的狀況下增長額外功能,裝飾器的返回值也是一個函數對象。它常常用於有切面需求的場景。好比:插入日誌、性能測試、事務處理、緩存、權限校驗等。有了裝飾器咱們就能夠抽離出大量的與函數功能無關的雷同代碼進行重用。 有關於具體的裝飾器的用法看這裏:裝飾器 - 廖雪峯的官方網站 (三)、簡要描述Python的垃圾回收機制(garbage collection) Python中的垃圾回收是以引用計數爲主,標記-清除和分代收集爲輔。 引用計數:Python在內存中存儲每一個對象的引用計數,若是計數變成0,該對象就會消失,分配給該對象的內存就會釋放出來。 標記-清除:一些容器對象,好比list、dict、tuple,instance等可能會出現引用循環,對於這些循環,垃圾回收器會定時回收這些循環(對象之間經過引用(指針)連在一塊兒,構成一個有向圖,對象構成這個有向圖的節點,而引用關係構成這個有向圖的邊)。 分代收集:Python把內存根據對象存活時間劃分爲三代,對象建立以後,垃圾回收器會分配它們所屬的代。每一個對象都會被分配一個代,而被分配更年輕的代是被優先處理的,所以越晚建立的對象越容易被回收。 若是你想要深刻了解Python的GC機制,點擊這裏:[轉載]Python垃圾回收機制--完美講解! (四)、Python多線程(multi-threading)。這是個好主意嗎? Python並不支持真正意義上的多線程,Python提供了多線程包。Python中有一個叫Global Interpreter Lock(GIL)的東西,它能確保你的代碼中永遠只有一個線程在執行。通過GIL的處理,會增長執行的開銷。這就意味着若是你先要提升代碼執行效率,使用threading不是一個明智的選擇,固然若是你的代碼是IO密集型,多線程能夠明顯提升效率,相反若是你的代碼是CPU密集型的這種狀況下多線程大部分是雞肋。 想要深刻詳細瞭解多線程,點擊這裏:詳解Python中的多線程編程_python 想了解一下IO密集和CPU密集能夠點擊這裏:CPU-bound(計算密集型) 和I/O bound(I/O密集型) (五)、 說明os,sys模塊不一樣,並列舉經常使用的模塊方法? 官方文檔: os模板提供了一種方便的使用操做系統函數的方法 sys模板可供訪問由解釋器使用或維護的變量和與解釋器交互的函數 另外一種回答: os模塊負責程序與操做系統的交互,提供了訪問操做系統底層的接口。sys模塊負責程序與Python解釋器的交互,提供了一系列的函數和變量用戶操做Python運行時的環境。一些經常使用的方法: 一些經常使用的用法示例: 想要了解更詳細的使用請訪問:os和sys模塊 - 君醉 (六)、什麼是lambda表達式?它有什麼好處? 簡單來講,lambda表達式一般是當你須要使用一個函數,可是又不想費腦殼去命名一個函數的時候使用,也就是一般所說的匿名函數。 lambda表達式通常的形式是:關鍵詞lambda後面緊接一個或多個參數,緊接一個冒號「:」,緊接一個表達式。lambda表達式是一個表達式不是一個語句。 想更加詳細的瞭解Python中的Lamdba表達式能夠點擊這裏:Lambda 表達式有何用處?如何使用? - Python (七)、Python中pass語句的做用是什麼? pass語句不會執行任何操做,通常做爲佔位符或者建立佔位程序 (八)、Python是如何進行類型轉換的? Python提供了將變量或值從一種類型轉換爲另外一種類型的內置方法。 (九)、Python裏面如何拷貝一個對象? Python中對象之間的賦值是按引用傳遞的,若是要拷貝對象須要使用標準模板中的copy copy.copy:淺拷貝,只拷貝父對象,不拷貝父對象的子對象。 copy.deepcopy:深拷貝,拷貝父對象和子對象。 (十)、__new__和__init__的區別。 __init__爲初始化方法,__new__方法是真正的構造函數。 __new__是實例建立以前被調用,它的任務是建立並返回該實例,是靜態方法 __init__是實例建立以後被調用的,而後設置對象屬性的一些初始值。 總結:__new__方法在__init__方法以前被調用,而且__new__方法的返回值將傳遞給__init__方法做爲第一個參數,最後__init__給這個實例設置一些參數。 想要更加詳細的瞭解這兩個方法,請點擊:Python中的__new__及其用法 (十一)、Python中單下劃線和雙下劃線分別是什麼? __name__:一種約定,Python內部的名字,用來與用戶自定義的名字區分開,防止衝突 _name:一種約定,用來指定變量私有 __name:解釋器用_classname__name來代替這個名字用以區別和其餘類相同的命名 想要更加詳細的瞭解這二者的區別,請點擊:Python中的下劃線(譯文) (十二)、說一說Python自省。 自省就是面向對象的語言所寫的程序在運行時,所能知道對象的類型。簡單一句話就是運行時可以得到對象的類型。好比:type()、dir()、getattr()、hasattr()、isinstance() 想要完整的理解Python自省,請點擊:Python自省(反射)指南 有關於元類以及單例模式會在後面文章中作詳細的解釋說明。