python高級面試題
A. python面試題,線程與進程的區別,Python中如何創建多線程
進程和線程這兩個概念屬於操作系統,我們經常聽說,但是可能很少有人會細究它們的含義。對於工程師而言,兩者的定義和區別還是很有必要了解清楚的。
首先說進程,進程可以看成是 CPU執行的具體的任務 。在操作系統當中,由於CPU的運行速度非常快,要比計算機當中的其他設備要快得多。比如內存、磁碟等等,所以如果CPU一次只執行一個任務,那麼會導致CPU大量時間在等待這些設備,這樣操作效率很低。為了提升計算機的運行效率,把機器的技能盡可能壓榨出來,CPU是輪詢工作的。也就是說 它一次只執行一個任務,執行一小段碎片時間之後立即切換 ,去執行其他任務。
所以在早期的單核機器的時候,看起來電腦也是並發工作的。我們可以一邊聽歌一邊上網,也不會覺得卡頓。但實際上,這是CPU輪詢的結果。在這個例子當中,聽歌的軟體和上網的軟體對於CPU而言都是 獨立的進程 。我們可以把進程簡單地理解成運行的應用,比如在安卓手機裡面,一個app啟動的時候就會對應系統中的一個進程。當然這種說法不完全准確, 一個應用也是可以啟動多個進程的 。
進程是對應CPU而言的,線程則更多針對的是程序。即使是CPU在執行當前進程的時候,程序運行的任務其實也是有分工的。舉個例子,比如聽歌軟體當中,我們需要顯示歌詞的字幕,需要播放聲音,需要監聽用戶的行為,比如是否發生了切歌、調節音量等等。所以,我們需要 進一步拆分CPU的工作 ,讓它在執行當前進程的時候,繼續通過輪詢的方式來同時做多件事情。
進程中的任務就是線程,所以從這點上來說, 進程和線程是包含關系 。一個進程當中可以包含多個線程,對於CPU而言,不能直接執行線程,一個線程一定屬於一個進程。所以我們知道,CPU進程切換切換的是執行的應用程序或者是軟體,而進程內部的線程切換,切換的是軟體當中具體的執行任務。
關於進程和線程有一個經典的模型可以說明它們之間的關系,假設CPU是一家工廠,工廠當中有多個車間。不同的車間對應不同的生產任務,有的車間生產汽車輪胎,有的車間生產汽車骨架。但是工廠的電力是有限的,同時只能滿足一個廠房的使用。
為了讓大家的進度協調,所以工廠需要輪流提供各個車間的供電。 這里的車間對應的就是進程 。
一個車間雖然只生產一種產品,但是其中的工序卻不止一個。一個車間可能會有好幾條流水線,具體的生產任務其實是流水線完成的,每一條流水線對應一個具體執行的任務。但是同樣的, 車間同一時刻也只能執行一條流水線 ,所以我們需要車間在這些流水線之間切換供電,讓各個流水線生產進度統一。
這里車間里的 流水線自然對應的就是線程的概念 ,這個模型很好地詮釋了CPU、進程和線程之間的關系。實際的原理也的確如此,不過CPU中的情況要比現實中的車間復雜得多。因為對於進程和CPU來說,它們面臨的局面都是實時變化的。車間當中的流水線是x個,下一刻可能就成了y個。
了解完了線程和進程的概念之後,對於理解電腦的配置也有幫助。比如我們買電腦,經常會碰到一個術語,就是這個電腦的CPU是某某核某某線程的。比如我當年買的第一台筆記本是4核8線程的,這其實是在說這台電腦的CPU有 4個計算核心 ,但是使用了超線程技術,使得可以把一個物理核心模擬成兩個邏輯核心。相當於我們可以用4個核心同時執行8個線程,相當於8個核心同時執行,但其實有4個核心是模擬出來的虛擬核心。
有一個問題是 為什麼是4核8線程而不是4核8進程呢 ?因為CPU並不會直接執行進程,而是執行的是進程當中的某一個線程。就好像車間並不能直接生產零件,只有流水線才能生產零件。車間負責的更多是資源的調配,所以教科書里有一句非常經典的話來詮釋: 進程是資源分配的最小單元,線程是CPU調度的最小單元 。
啟動線程Python當中為我們提供了完善的threading庫,通過它,我們可以非常方便地創建線程來執行多線程。
首先,我們引入threading中的Thread,這是一個線程的類,我們可以通過創建一個線程的實例來執行多線程。
from threading import Thread t = Thread(target=func, name='therad', args=(x, y)) t.start()簡單解釋一下它的用法,我們傳入了三個參數,分別是 target,name和args ,從名字上我們就可以猜測出它們的含義。首先是target,它傳入的是一個方法,也就是我們希望多線程執行的方法。name是我們為這個新創建的線程起的名字,這個參數可以省略,如果省略的話,系統會為它起一個系統名。當我們執行Python的時候啟動的線程名叫MainThread,通過線程的名字我們可以做區分。args是會傳遞給target這個函數的參數。
我們來舉個經典的例子:
import time, threading # 新線程執行的代碼: def loop(n): print('thread %s is running...' % threading.current_thread().name) for i in range(n): print('thread %s >>> %s' % (threading.current_thread().name, i)) time.sleep(5) print('thread %s ended.' % threading.current_thread().name) print('thread %s is running...' % threading.current_thread().name) t = threading.Thread(target=loop, name='LoopThread', args=(10, )) t.start() print('thread %s ended.' % threading.current_thread().name)我們創建了一個非常簡單的loop函數,用來執行一個循環來列印數字,我們每次列印一個數字之後這個線程會睡眠5秒鍾,所以我們看到的結果應該是每過5秒鍾屏幕上多出一行數字。
我們在Jupyter里執行一下:
表面上看這個結果沒毛病,但是其實有一個問題,什麼問題呢? 輸出的順序不太對 ,為什麼我們在列印了第一個數字0之後,主線程就結束了呢?另外一個問題是,既然主線程已經結束了, 為什麼Python進程沒有結束 , 還在向外列印結果呢?
因為線程之間是獨立的,對於主線程而言,它在執行了t.start()之後,並 不會停留,而是會一直往下執行一直到結束 。如果我們不希望主線程在這個時候結束,而是阻塞等待子線程運行結束之後再繼續運行,我們可以在代碼當中加上t.join()這一行來實現這點。
t.start() t.join() print('thread %s ended.' % threading.current_thread().name)join操作可以讓主線程在join處掛起等待,直到子線程執行結束之後,再繼續往下執行。我們加上了join之後的運行結果是這樣的:
這個就是我們預期的樣子了,等待子線程執行結束之後再繼續。
我們再來看第二個問題,為什麼主線程結束的時候,子線程還在繼續運行,Python進程沒有退出呢?這是因為默認情況下我們創建的都是用戶級線程,對於進程而言, 會等待所有用戶級線程執行結束之後才退出 。這里就有了一個問題,那假如我們創建了一個線程嘗試從一個介面當中獲取數據,由於介面一直沒有返回,當前進程豈不是會永遠等待下去?
這顯然是不合理的,所以為了解決這個問題,我們可以把創建出來的線程設置成 守護線程 。
守護線程守護線程即daemon線程,它的英文直譯其實是後台駐留程序,所以我們也可以理解成 後台線程 ,這樣更方便理解。daemon線程和用戶線程級別不同,進程不會主動等待daemon線程的執行, 當所有用戶級線程執行結束之後即會退出。進程退出時會kill掉所有守護線程 。
我們傳入daemon=True參數來將創建出來的線程設置成後台線程:
t = threading.Thread(target=loop, name='LoopThread', args=(10, ), daemon=True)這樣我們再執行看到的結果就是這樣了:
這里有一點需要注意,如果你 在jupyter當中運行是看不到這樣的結果的 。因為jupyter自身是一個進程,對於jupyter當中的cell而言,它一直是有用戶級線程存活的,所以進程不會退出。所以想要看到這樣的效果,只能通過命令行執行Python文件。
如果我們想要等待這個子線程結束,就必須通過join方法。另外,為了預防子線程鎖死一直無法退出的情況, 我們還可以 在joih當中設置timeout ,即最長等待時間,當等待時間到達之後,將不再等待。
比如我在join當中設置的timeout等於5時,屏幕上就只會輸出5個數字。
另外,如果沒有設置成後台線程的話,設置timeout雖然也有用,但是 進程仍然會等待所有子線程結束 。所以屏幕上的輸出結果會是這樣的:
雖然主線程繼續往下執行並且結束了,但是子線程仍然一直運行,直到子線程也運行結束。
關於join設置timeout這里有一個坑,如果我們只有一個線程要等待還好,如果有多個線程,我們用一個循環將它們設置等待的話。那麼 主線程一共會等待N * timeout的時間 ,這里的N是線程的數量。因為每個線程計算是否超時的開始時間是上一個線程超時結束的時間,它會等待所有線程都超時,才會一起終止它們。
比如我這樣創建3個線程:
ths = [] for i in range(3): t = threading.Thread(target=loop, name='LoopThread' + str(i), args=(10, ), daemon=True) ths.append(t) for t in ths: t.start() for t in ths: t.join(2)最後屏幕上輸出的結果是這樣的:
所有線程都存活了6秒。
總結在今天的文章當中,我們一起簡單了解了 操作系統當中線程和進程的概念 ,以及Python當中如何創建一個線程,以及關於創建線程之後的相關使用。
多線程在許多語言當中都是至關重要的,許多場景下必定會使用到多線程。比如 web後端,比如爬蟲,再比如游戲開發 以及其他所有需要涉及開發ui界面的領域。因為凡是涉及到ui,必然會需要一個線程單獨渲染頁面,另外的線程負責准備數據和執行邏輯。因此,多線程是專業程序員繞不開的一個話題,也是一定要掌握的內容之一。
B. python面試題總結1-內存管理機制
(1).引用計數
(2). 垃圾回收
(3). 內存池機制
在python中每創建一個對象,對應的會有一個引用計數,當發生賦值操作如a=b,對應的b的引用計數會自動加1,當引用的對象被清除或者函數結束時,引用計數會自動減1。
在python中使用引用計數,標記清楚,分代回收三種方式進行垃圾回收。
其中,引用計數當對象的引用計數歸0時,對象會自動被清除。標記清除機制是首先遍歷所有對象,如果對象可達,就說明有變數引用它,則標記其為可達的。如果不可達,則對其進行清除。分代回收是當對象創建時被標記為第0代,經過一次垃圾回收之後,餘下的對象被標記為第1代,最高為第2代。其原理是,對象的生存期越長,月可能不是垃越。
ython語言雖然提供了對內存的垃圾收集機制,但實際上它將不用的內存放到內存池而不是返回給操作系統,所以就有了以下:
1 Pymalloc機制;這個主要是為了加速Python的執行效率,Python引入了一個內存池機制,用於管理,為了對小塊內存的申請和釋放。
2 Python中所有小於256個位元組的對象都是依靠pymalloc分配器來實現的,而稍大的對象用的則是系統的malloc。
3 對於Python對象,比如整數、浮點數和List這些,都有自己獨立的內存池,對象間並不共享他們的內存池。換句話說就是,假設你分配並且釋放了大量的整數,那麼用於緩存這些整數的內存就不能再分配給浮點數。
C. Python面試數據分析,爬蟲和深度學習一般都問什麼問題,筆試題目有哪些
簡單羅列些:
1.數據清洗與處理:數據讀取read_csv等,數據表構建dataframe等,數據整合concat/join/merge等,表結構處理以及切片iloc/loc等,數據統計describe/isnull/sum/apply等,圖表展示plot,數據透視表pivot_table等,異常值與缺失數據統計與處理,相關性檢驗
2.機器學習模型構建:svm,logistic,knn等
3.爬蟲:request包
4.深度學習:CNN,RNN,圖像處理,音頻處理,語義理解。
D. 設整形變數x=10,則表達式2<x<8的值
編輯
:kenwoodjw
對於機器學習演算法工程師而言,Python是不可或缺的語言,它的優美與簡潔令人無法自拔。那麼你過Python編程面試題嗎?從Python基礎到網頁爬蟲你是否能全方位Hold住?今天,為讀者們推薦一個Github項目。
在這個項目中, kenwoodjw 准備了近 300 道 Python 面試題,同時還包含解決方案與代碼。主要從 Python 基礎、高級語句、網頁應用、資料庫和測試等角度提問,讀者可只自己需要的領域。目前該項目已經完成了很多基礎和高級面試題,本文主要摘取一些 Python 面試題供大家參考。
項目地址:https://github.com/kenwoodjw/python_interiew_question
總體而言,項目有近300道面試題。雖然該項目剛開始創建,但很多Python面試題都已經提供決方案。如下所示為面試題示例:
本文截取了一些面試題及解決方案:
Python 基礎文件操作模塊與包數據類型企業面試題Python 高級設計模式系統編程如果希望機器學習面試題,可閱讀:春招已近,這份GitHub萬星的ML演算法面試大全請收下
Python 基礎
什麼是 Python?根據Python 創建者 Guido an Rossum 所言,Python是一種高級編程語言,其設計的核心理念是代碼的易讀性,以及允許編程者通過若干行代碼輕松表達想法創意。實際上,很多開發者選擇學習 Python 的首要原因是其編程的優美性,用它編碼和表達想法非常自然。
文件操作
1.若有一個jsonline格式的文件file.txt,大小約為10K,我們的處理方式為:
defget_lines(): l = []with open('file.txt', 'rb') as f:for eachline in f: l.append(eachline)return lif __name__ == '__main__':for e in get_lines(): process(e) #處理每一行數據
現在要處理一個大小為10G的file.txt文件,但是內存只有4G。如果在只修改get_lines 函數而其他代碼保持不變的情況下,應該如何實現?需要考慮的問題都有那些?
defget_lines(): l = []with open('file.txt','rb') as f: data = f.readlines(60000) l.append(data)yield l
要考慮的問題有:內存只有4G,無法一次性讀入10G文件。而分批讀入數據要記錄每次讀入數據的位置,且分批每次讀取得太小會在讀取操作上花費過多時間。
模塊與包
2.如何輸入日期, 判斷這一天是這一年的第幾天?
import datetimedefdayofyear(): year = input("請輸入年份: ") month = input("請輸入月份: ") day = input("請輸入天: ") date1 = datetime.date(year=int(year),month=int(month),day=int(day)) date2 = datetime.date(year=int(year),month=1,day=1)return (date1-date2).days+1數據類型
3.如何反轉字元串"aStr"?
print("aStr"[::-1])4.下面代碼的輸出結果將是什麼?會報錯嗎?
list = ['a','b','c','d','e']print(list[10:])
代碼將輸出[],並不會產生IndexError 錯誤。如果嘗試用超出成員的個數的index來獲取某個列表的成員,那就會報錯。例如,嘗試獲取 list[10] 和之後的成員,會導致IndexError。然而當我們嘗試獲取列表的切片時,開始的index超過成員個數並不會產生IndexError,而是僅僅返回一個空列表。因為並不會報錯,所以這種Bug很難追蹤到。
5.請寫出一段Python代碼,實現刪除list裡面的重復元素?
l1 = ['b','c','d','c','a','a']l2 = list(set(l1))print(l2)用list類的sort方法可以保證順序不變:
l1 = ['b', 'c', 'd', 'c', 'a', 'a']l2 = list(set(l1))l2.sort(key=l1.index)print(l2)也可以這樣寫:
l1 = ['b', 'c', 'd', 'c', 'a', 'a']l2 = sorted(set(l1), key=l1.index)print(l2)
也可以用遍歷:
l1 = ['b', 'c', 'd', 'c', 'a', 'a']l2 = []for i in l1:ifnot i in l2: l2.append(i)print(l2)企業面試題
6.設計實現遍歷目錄與子目錄,抓取.pyc文件
第一種方法:
import osdefgetFiles(dir, suffix): res = []for root, dirs, files in os.walk(dir):for filename in files: name, suf = os.path.splitext(filename)if suf == suffix: res.append(os.path.join(root, filename)) print(res)getFiles("./", '.pyc')
第二種方法:
import osdefpick(obj):try:if obj.[-4:] == ".pyc": print(obj)except:returnNonedefscan_path(ph): file_list = os.listdir(ph)for obj in file_list:if os.path.isfile(obj): pick(obj)elif os.path.isdir(obj): scan_path(obj)if __name__ == '__main__': path = input('輸入目錄') scan_path(path)
7.如何反轉一個整數,例如-123--> -321?
classSolution(object):defreerse(self, x):if-10 < x=""><>return x str_x = str(x)if str_x[0] != "-": str_x = str_x[::-1] x = int(str_x)else: str_x = str_x[1:][::-1] x = int(str_x) x = -xreturn x if-2147483648 < x=""><>if __name__ == '__main__': s = Solution() reerse_int = s.reerse(-120) print(reerse_int)
Python高級
Python高級包含很多重要的模塊,例如函數、類和實例、系統編程、正則表達式、網路編程等等。根據這些高級屬性,Python可用於數據科學、網頁開發、機器學習等等。
設計模式
8.對設計模式的理解,簡述你的設計模式?
設計模式是為我們經常會碰到的一些編程問題構建的可重用解決方案,它是總結性和經優化的。一個設計模式並不像一個類或一個庫那樣能夠直接作用於我們的代碼,反之,設計模式更為高級,它是一種在特定情形下實現的方法模板。常見的是工廠模式和單例模式。
單例模式應用的場景一般發現在以下條件下: 資源共享的情況下,避免由於資源操作時導致的性能或損耗等,如日誌文件,應用配置。控制資源的情況下,方便資源之間的互相通信。
9.生成器和迭代器的區別?
迭代器是一個更抽象的概念,任何對象,如果它的類有 next 方法和 iter 方法返回自己本身,它就是可迭代的。對於 string、list、dict、tuple 等這類容器對象,使用for循環遍歷是很方便的,for 語句實際上會對容器對象調用 iter() 函數。iter() 會返回一個定義了 next() 方法的迭代器對象,它在容器中逐個訪問容器內元素,在沒有後續元素時,next()會拋出一個StopIteration異常。
生成器(Generator)是創建迭代器的簡單而強大的工具。它們寫起來就像是正規的函數,只是在需要返回數據的時候使用yield語句。生成器能做到迭代器能做的所有事,而且因為自動創建iter()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表達式取代列表解析可以同時節省內存。除了創建和保存程序狀態的自動方法,當發生器終結時,還會自動拋出StopIteration異常。
10.對裝飾器的理解,你能寫出一個計時器裝飾器,它能記錄函數的執行時間嗎?
裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。
import timedeftimeit(func):defwrapper(): start = time.clock() func() end = time.clock() print('used:',end-start)return wrapper @timeitdeffoo(): print('in foo()'foo())
系統編程
11.介紹一下你的進程。
程序運行在操作系統上的一個實例,就稱之為進程。進程需要相應的系統資源:內存、時間片、pid。創建進程: 首先要導入multiprocessing中的Process;創建一個Process對象;創建Process對象時,可以傳遞參數。
p = Process(target=XXX, args=(tuple,), kwargs={key: alue})target = XXX # 指定的任務函數,不用加()args = (tuple,)kwargs = {key: alue} # 給任務函數傳遞的參數使用start()啟動進程 結束進程 給子進程指定函數傳遞參數Demo
import osfrom mulitprocessing import Processimport timedefpro_func(name, age, **kwargs):for i in range(5): print("子進程正在運行中,name=%s,age=%d,pid=%d" % (name, age, os.getpid())) print(kwargs) time.sleep(0.2)if __name__ == "__main__":# 創建Process對象 p = Process(target=pro_func, args=('小明', 18), kwargs={'m': 20})# 啟動進程 p.start() time.sleep(1)# 1秒鍾之後,立刻結束子進程 p.terminate() p.join()12.談談你對多進程、多線程、以及協程的理解,項目是否用?
進程:一個運行的程序(代碼)就是一個進程,沒有運行的代碼叫程序,進程是系統資源分配的最小單位,進程擁有自己獨立的內存空間,所有進程間數據不共享,開銷大。線程: cpu調度執行的最小單位,也叫執行路徑,不能獨立存在,依賴進程存在,一個進程至少有一個線程,叫主線程,而多個線程共享內存可以極大地提高了程序的運行效率。協程: 是一種用戶態的輕量級線程,協程的調度完全由用戶控制,協程擁有自己的寄存器上下文和棧。協程調度時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧,直接操中棧則基本沒有內核切換的開銷,可以不加鎖的訪問全局變數,所以上下文的切換非常快。
關於系統編程還有很多問題,例如:
本文為編輯,請聯系本獲得授權。
E. 面試經驗丨百度 測試開發工程師 面試題集(含面試題答案),來瞧瞧
IT互聯網的飛速發展,很多人選擇從計算機方面開發著手,在整個計算機行業的,不同崗位所需要具備的能力是不同的。這次分享的是我一個朋友網路面試測開的面試題。
面試時間:21年4月。
1.項目介紹(難點,解決方案)
2.介紹黑盒測試和白盒測試
3.Java中的int和Integer
4.Java的許可權修飾符(public、private、default、protect的作用域)
5.代碼:判斷鏈表是否有環,找出環的長度
6.代碼:手寫字元串比較函數strcmp,設計測試用例
7.一部電梯設計測試用例(一般設計測試用例從功能性、性能性、安全性、易用性考慮)
8.2個資料庫表:表1(id name),表2(id sroce class),找出姓名張三的分數和班級
select sroce,class from table2 where table2.id = (select id from table1 where name = "張三")
9.Liunx查看指定進程 ps -ef|grep 進程名 查看埠 lsof -i:埠號
10.計網TCP/UDP的區別(有4個區別,但是突然有點腦子短路了,只記起來2個)
11.HTTP狀態碼
1.linux基本操作
2.http請求
3.三次握手四次揮手
4.網頁登錄,寫測試用例
5.網路地圖,寫測試用例
6.python init
7.python深拷貝淺拷貝
1.棧和堆的區別
2.多態的意義,用在什麼地方
3.內存泄漏和內存溢出有沒有什麼聯系
4.死鎖
5.new、delete、malloc、free區別
6.冒泡
7.出現次數最多的數
8.shell命令
1.Python常用內置模塊
2.List與numpy的區別(項目里用了numpy)
3.With機制及如何實現
4.Range的方法
5.迭代器的了解
6.c++和python的並發編程了解多少
7.Linux常用命令
8.網路層作用是什麼
9.Tcp/udp的區別及應用場景
10.什麼時候創建索引
11.索引的類別
12.索引的數據結構及具體實現介紹
13.不同資料庫的比較,即對不同場景怎樣選用資料庫
14.在字元串中尋找長度最長的迴文字元串,可假設isPalindrome返回是否是迴文的判斷
1.快速排序
2.測試快速排序
3.移動通信是什麼
4.osi七層模型。
5.應用層用什麼協議傳輸視頻和傳輸文字的
6.應用層怎麼區分不同應用進程
7.TCP、UDP協議的區別
8.在Web上搜索東西的過程經歷了什麼,詳細說說
9.微信聊天界面的測試用例
10.Linux常用命令
11.說一說項目以及項目統籌
12.覺得測試是做什麼
13.你覺得項目的流程是怎麼樣
14.項目上線前是交由產品還是測試人員測試
15.你覺得測試在項目里是怎樣的角色。
我根據這次面試整理了下資料,資料實在太多了,所以只把部分截圖放出來。提醒大家一下,資料按需索取,千萬不要一味的收藏,反正你都看不完的。把時間浪費在找資料上不值得。
如何獲取免費架構學習資料?
關注我+轉發文章+私信【測試】獲取這份全面的資料。
F. 這個python題目怎麼寫
無意間,看到這么一道Python面試題:以下代碼將輸出什麼?
def testFun:
temp = [lambda x : i*x for i in range(4)]
return temp
for everyLambda in testFun:
print (everyLambda(2))
腦中默默一想,這還用說么,肯定是:
0
2
4
6
最後一看答案,竟然是:
6
6
6
6
於是帶著懷疑的心態(其實是不服輸,不認錯),打開編輯器,快速一敲,果然是:
懷疑了人生半天,本來還想黑,WTF Python…然後才想通是自己太生疏......
最後發現原因竟是:Python 的閉包的後期綁定導致的 late binding。
這意味著在閉包中的變數是在內部函數被調用的時候被查找,所以當任何testFun 返回的函數被調用,i 的值是在它被調用時的周圍作用域中查找。
也就是說無論哪個返回的函數被調用,for 循環都已經完成了,i 最後的值是 3,因此,每個返回的函數 testFun 的值都是 3。
因此一個等於 2 的值被傳遞進以上代碼,它們將返回一個值 6 (比如:3 x 2)。
究竟如何才能實現出這樣的結果呢?
0
2
4
6
想了想,若能立即綁定參數,或者直接不用閉包總該行吧,用另一種方式避免 i 的改寫。
回憶了之前所學知識,最後醞釀出了四種解決方案。
第一種:創建一個閉包,通過使用默認參數立即綁定它的參數
def testFun:
temp = [lambda x, i=i: i * x for i in range(4)]
return temp
for everyLambda in testFun:
print(everyLambda(2))
第二種:使用functools.partial 函數,把函數的某些參數(不管有沒有默認值)給固定住(也就是相當於設置默認值)
from functools import partial
from operator import mul
def testFun:
return [partial(mul, i) for i in range(4)]
for everyLambda in testFun:
print(everyLambda(2))
第三種:優雅的寫法,直接用生成器
def testFun:
return (lambda x, i=i: i * x for i in range(4))
for everyLambda in testFun:
print(everyLambda(2))
第四種:利用yield的惰性求值的思想
def testFun:
for i in range(4):
yield lambda x: i * x
for everyLambda in testFun:
print(everyLambda(2))
最終運行結果:
有了解決方案後,又陷入了懷疑自己,這個題目究竟是考察的是什麼?是在考面試者閉包相關知識以及Python 的閉包的後期綁定問題么?
若將題目改成:以下代碼輸出的結果是(0,2,4,6)么?如果不是,你將會怎麼做,讓它變成(0,2,4,6)?這樣會不會更有意思點呢?歡迎大家出妙招,看究竟有多少招?(哈哈哈!!!)
G. BAT面試題28:Python是如何進行內存管理的
Python的內存管理,一般從以下三個方面來說:
1)對象的引用計數機制(四增五減)
2)垃圾回收機制(手動自動,分代回收)
3)內存池機制(大m小p)
1)對象的引用計數機制
要保持追蹤內存中的對象,Python使用了引用計數這一簡單的技術。sys.getrefcount(a)可以查看a對象的引用計數,但是比正常計數大1,因為調用函數的時候傳入a,這會讓a的引用計數+1
2)垃圾回收機制
吃太多,總會變胖,Python也是這樣。當Python中的對象越來越多,它們將占據越來越大的內存。不過你不用太擔心Python的體形,它會在適當的時候「減肥」,啟動垃圾回收(garbage
collection),將沒用的對象清除
從基本原理上,當Python的某個對象的引用計數降為0時,說明沒有任何引用指向該對象,該對象就成為要被回收的垃圾了
比如某個新建對象,它被分配給某個引用,對象的引用計數變為1。如果引用被刪除,對象的引用計數為0,那麼該對象就可以被垃圾回收。
然而,減肥是個昂貴而費力的事情。垃圾回收時,Python不能進行其它的任務。頻繁的垃圾回收將大大降低Python的工作效率。如果內存中的對象不多,就沒有必要總啟動垃圾回收。
所以,Python只會在特定條件下,自動啟動垃圾回收。當Python運行時,會記錄其中分配對象(object
allocation)和取消分配對象(object deallocation)的次數。當兩者的差值高於某個閾值時,垃圾回收才會啟動。
我們可以通過gc模塊的get_threshold()方法,查看該閾值。
3)內存池機制
Python中有分為大內存和小內存:(256K為界限分大小內存)
1、大內存使用malloc進行分配
2、小內存使用內存池進行分配
python中的內存管理機制都有兩套實現,一套是針對小對象,就是大小小於256K時,pymalloc會在內存池中申請內存空間;當大於256K時,則會直接執行系統的malloc的行為來申請內存空間。
H. 2022年Python技術類面試題總結(面試題+答案解析)
這是一位有著五年 Python 經驗的好友最近對 Python 崗位面試後的一篇經驗總結,從 Python 就業方向到 Python 面試題。
Python 就業方向 :
下面是 Python 面試知識點,總結了華為、阿里巴巴等互聯網公司 Python 常問面試題。每道題都提供參考答案,希望能夠幫助你在求職面試中脫穎而出,找到一份高薪工作。
這些面試題分為 Python 基礎和 Python高級,內容包含: 基礎語法、文件操作、模塊與包、數據類型、元類、內存管理與垃圾回收機制以及 Python 函數 等知識點。
(一) Python 基礎語法
(二) 文件操作
(三) 模塊與包
(四) 數據類型
(五)企業面試題
(一) 元類
(二)內存管理與垃圾回收機制
(三)函數
(四) 面向對象
由於篇幅有限,這份 Python 面試寶典已經被整理成了PDF文檔,有需要 Python 面試寶典全套完整文檔(面試題+答案解析)的可以 免費領取!