【文章內(nèi)容簡(jiǎn)介】
因?yàn)闆](méi)有版本控制的代碼,就像沒(méi)有杯子的咖啡。有時(shí)候我們需要寫(xiě)一些一次性的、可以隨手扔掉的腳本,這種情況下不作版本控制沒(méi)關(guān)系。但是如果你面對(duì)的是大量的代碼,使用版本控制系統(tǒng)是有利的。版本控制能夠幫你追蹤誰(shuí)對(duì)代碼庫(kù)做了什么操作;發(fā)現(xiàn)新引入了什么bug;管理你的軟件的不同版本和發(fā)行版;在團(tuán)隊(duì)成員中分享源代碼;部署及其他自動(dòng)化處理。它能讓你回滾到出現(xiàn)問(wèn)題之前的版本,單憑這點(diǎn)就特別棒了。還有其他的好功能。怎么一個(gè)棒字了得!34“猴子補(bǔ)丁”(monkey patching)指的是什么?這種做法好嗎?答案:“猴子補(bǔ)丁”就是指,在函數(shù)或?qū)ο笠呀?jīng)定義之后,再去改變它們的行為。舉個(gè)例子:import datetime = lambda: (2012, 12, 12)大部分情況下,這是種很不好的做法 因?yàn)楹瘮?shù)在代碼庫(kù)中的行為最好是都保持一致。打“猴子補(bǔ)丁”的原因可能是為了測(cè)試。mock包對(duì)實(shí)現(xiàn)這個(gè)目的很有幫助。為什么提這個(gè)問(wèn)題?答對(duì)這個(gè)問(wèn)題說(shuō)明你對(duì)單元測(cè)試的方法有一定了解。你如果提到要避免“猴子補(bǔ)丁”,可以說(shuō)明你不是那種喜歡花里胡哨代碼的程序員(公司里就有這種人,跟他們共事真是糟糕透了),而是更注重可維護(hù)性。還記得KISS原則碼?答對(duì)這個(gè)問(wèn)題還說(shuō)明你明白一些Python底層運(yùn)作的方式,函數(shù)實(shí)際是如何存儲(chǔ)、調(diào)用等等。另外:如果你沒(méi)讀過(guò)mock模塊的話(huà),真的值得花時(shí)間讀一讀。這個(gè)模塊非常有用。35閱讀下面的代碼,它的輸出結(jié)果是什么?class A(object): def go(self): print go A go! def 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 stop 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() 說(shuō)明下列代碼的輸出結(jié)果()()()()()()()()()()()()()()()答案輸出結(jié)果以注釋的形式表示:() go A go!() go A go! go B go!() go A go! go C go!() go A go! go C go! go B go! go D go!() go A go! go C go! go B go!() stop A stop!() stop A stop!() stop A stop! stop C stop!() stop A stop! stop C stop! stop D stop!() stop A stop!() ... Exception: Not Implemented() ... Exception: Not Implemented() ... Exception: Not Implemented() wait D wait!() ...Exception: Not Implemented為什么提這個(gè)問(wèn)題?因?yàn)槊嫦驅(qū)ο蟮木幊陶娴恼娴暮苤匾?。不騙你。答對(duì)這道問(wèn)題說(shuō)明你理解了繼承和Python中super函數(shù)的用法。36閱讀下面的代碼,它的輸出結(jié)果是什么?class Node(object): def __init__(self,sName): = [] = sName def __repr__(self): return Node 39。{}39。.format() def append(self,*args,**kwargs): (*args,**kwargs) def print_all_1(self): print self for oChild in : () def print_all_2(self): def gen(o): lAll = [o,] while lAll: oNext = (0) () yield oNext for oNode in gen(self): print oNodeoRoot = Node(root)oChild1 = Node(child1)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(child10)(oChild1)(oChild2)(oChild3)(oChild4)(oChild5)(oChild6)(oChild7)(oChild8)(oChild9)(oChild10) 說(shuō)明下面代碼的輸出結(jié)果()()答案()會(huì)打印下面的結(jié)果:Node 39。root39。Node 39。child139。Node 39。child439。Node 39。child739。Node 39。child539。Node 39。child239。Node 39。child639。Node 39。child1039。Node 39。child339。Node 39。child839。Node 39。child939。()會(huì)打印下面的結(jié)果:Node 39。root39。Node 39。child139。Node 39。child239。Node 39。child339。Node 39。child439。Node 39。child539。Node 39。child639。Node 39。child839。Node 39。child939。Node 39。child739。Node 39。child1039。為什么提這個(gè)問(wèn)題?因?yàn)閷?duì)象的精髓就在于組合(position)與對(duì)象構(gòu)造(object construction)。對(duì)象需要有組合成分構(gòu)成,而且得以某種方式初始化。這里也涉及到遞歸和生成器(generator)的使用。生成器是很棒的數(shù)據(jù)類(lèi)型。你可以只通過(guò)構(gòu)造一個(gè)很長(zhǎng)的列表,然后打印列表的內(nèi)容,就可以取得與print_all_2類(lèi)似的功能。生成器還有一個(gè)好處,就是不用占據(jù)很多內(nèi)存。有一點(diǎn)還值得指出,就是print_all_1會(huì)以深度優(yōu)先(depthfirst)的方式遍歷樹(shù)(tree),而print_all_2則是寬度優(yōu)先(widthfirst)。有時(shí)候,一種遍歷方式比另一種更合適。但這要看你的應(yīng)用的具體情況。?答:try…except…except…[else…][finally…]執(zhí)行try下的語(yǔ)句,如果引發(fā)異常,則執(zhí)行過(guò)程會(huì)跳到except語(yǔ)句。對(duì)每個(gè)except分支順序嘗試執(zhí)行,如果引發(fā)的異常與except中的異常組匹配,執(zhí)行相應(yīng)的語(yǔ)句。如果所有的except都不匹配,則異常會(huì)傳遞到下一個(gè)調(diào)用本代碼的最高層try代碼中。try下的語(yǔ)句正常執(zhí)行,則執(zhí)行else塊代碼。如果發(fā)生異常,就不會(huì)執(zhí)行如果存在finally語(yǔ)句,最后總是會(huì)執(zhí)行。?答:pass語(yǔ)句不會(huì)執(zhí)行任何操作,一般作為占位符或者創(chuàng)建占位程序,whileFalse:pass()函數(shù)的用法?答:列出一組數(shù)據(jù),經(jīng)常用在for in range()循環(huán)中?答:可以使用re模塊中的sub()函數(shù)或者subn()函數(shù)來(lái)進(jìn)行查詢(xún)和替換,格式:sub(replacement, string[,count=0])(replacement是被替換成的文本,string是需要被替換的文本,count是一個(gè)可選參數(shù),指最大被替換的數(shù)量) import rep=(‘blue|white|red’)print((‘colour’,39。blue socks and red shoes’))colour socks and colourshoesprint((‘colour’,39。blue socks and red shoes’,count=1))colour socks and redshoessubn()方法執(zhí)行的效果跟sub()一樣,不過(guò)它會(huì)返回一個(gè)二維數(shù)組,包括替換后的新的字符串和總共替換的數(shù)量()和search()的區(qū)別?答:re模塊中match(pattern,string[,flags]),檢查string的開(kāi)頭是否與pattern匹配。re模塊中research(pattern,string[,flags]),在string搜索pattern的第一個(gè)匹配值。print((‘super’, ‘superstition’).span())(0, 5)print((‘super’, ‘insuperable’))Noneprint((‘super’, ‘superstition’).span())(0, 5)print((‘super’, ‘insuperable’).span())(2, 7) tag的時(shí)候,.*和.*?有什么區(qū)別?答:術(shù)語(yǔ)叫貪婪匹配( .* )和非貪婪匹配(.*? )例如:test.* :test.*? :?答:random模塊隨機(jī)整數(shù):(a,b):返回隨機(jī)整數(shù)x,a=x=b(start,stop,[,step]):返回一個(gè)范圍在(start,stop,step)之間的隨機(jī)整數(shù),不包括結(jié)束值。隨機(jī)實(shí)數(shù):( ):返回0到1之間的浮點(diǎn)數(shù)(a,b):返回指定范圍內(nèi)的浮點(diǎn)數(shù)。?答:PyChecker是一個(gè)python代碼的靜態(tài)分析工具,它可以幫助查找python代碼的bug, 會(huì)對(duì)代碼的復(fù)雜度和格式提出警告Pylint是另外一個(gè)工具可以進(jìn)行codingstandard檢查?答:解決方法是在function的開(kāi)始插入一個(gè)global聲明:def f()global x,雙引號(hào),三引號(hào)的區(qū)別答:?jiǎn)我?hào)和雙引號(hào)是等效的,如果要換行,需要符號(hào)(\),三引號(hào)則可以直接換行,并且可以包含注釋如果要表示Let’s go 這個(gè)字符串單引號(hào):s4 = ‘Let\’s go’雙引號(hào):s5 = “Let’s go”s6 = ‘I realy like“python”!’這就是單引號(hào)和雙引號(hào)都可以表示字符串的原因了46 Python和多線(xiàn)程(multithreading)。這是個(gè)好主意碼?列舉一些讓Python代碼以并行方式運(yùn)行的方法。答案Python并不支持真正意義上的多線(xiàn)程。Python中提供了多線(xiàn)程包,但是如果你想通過(guò)多線(xiàn)程提高代碼的速度,使用多線(xiàn)程包并不是個(gè)好主意。Python中有一個(gè)被稱(chēng)為Global Interpreter Lock(GIL)的東西,它會(huì)確保任何時(shí)候你的多個(gè)線(xiàn)程中,只有一個(gè)被執(zhí)行。線(xiàn)程的執(zhí)行速度非常之快,會(huì)讓你誤以為線(xiàn)程是并行執(zhí)行的,但是實(shí)際上都是輪流執(zhí)行。經(jīng)過(guò)GIL這一道關(guān)卡處理,會(huì)增加執(zhí)行的開(kāi)銷(xiāo)。這意味著,如果你想提高代碼的運(yùn)行速度,使用threading包并不是一個(gè)很好的方法。不過(guò)還是有很多理由促使我們使用threading包的。如果你想同時(shí)執(zhí)行一些任務(wù),而且不考慮效率問(wèn)題,那么使用這個(gè)包是完全沒(méi)問(wèn)題的,而且也很方便。但是大部分情況下,并不是這么一回事,你會(huì)希望把多線(xiàn)程的部分外包給操作系統(tǒng)完成(通過(guò)開(kāi)啟多個(gè)進(jìn)程),或者是某些調(diào)用你的Python代碼的外部程序(例如Spark或Hadoop),又或者是你的Python代碼調(diào)用的其他代碼(例如,你可以在Python中調(diào)用C函數(shù),用于處理開(kāi)銷(xiāo)較大的多線(xiàn)程工作)。為什么提這個(gè)問(wèn)題因?yàn)镚IL就是個(gè)混賬東西(Ahole)。很多人花費(fèi)大量的時(shí)間,試圖尋找自己多線(xiàn)程代碼中的瓶頸,直到他們明白GIL的存在。47 將下面的函數(shù)按照?qǐng)?zhí)行效率高低排序。它們都接受由0至1之間的數(shù)字構(gòu)成的列表作為輸入。這個(gè)列表可以很長(zhǎng)。一個(gè)輸入列表的示例如下:[() for i in range(100000)]。你如何證明自己的答案是正確的。def f1(lIn): l1 = sorted(lIn) l2 = [i for i in l1 if i] return [i*i for i in l2]def f2(lIn): l1 = [i for i in lIn if i] l2 = sorted(l1) return [i*i for i in l2]def f3(lIn): l1 = [i*i for i in lIn] l2 = sorted(l1) return [i for i in l1 if i(*)]答案按執(zhí)行效率從高到低排列:ff1和f3。要證明這個(gè)答案是對(duì)的,你應(yīng)該知道如何分析自己代碼的性能。Python中有一個(gè)很好的程序分析包,可以滿(mǎn)足這個(gè)需求。import cProfilelIn = [() for