1御吞、大數(shù)據(jù)的文件的讀取
① 讀取大幾G的大文件,可以利用生成器 generator
② 對可迭代對象 file漓藕,進行迭代遍歷:for line in file魄藕,會自動地使用緩沖IO(buffered IO)以及內存管理,而不必擔心任何大文件的問題撵术。
with open('filename') as file:
for line in file:
do_things(line)
2背率、迭代器和生成器區(qū)別 ?
(1)迭代器是一個更抽象的概念嫩与,任何對如果它類有 next方法和方法和 iter方法返回自己本身 寝姿。對于 strings、list划滋、dict饵筑、tuple等這類容器對象,使用 for循環(huán)遍歷是很方便的处坪。在后臺for語句對容器象調用iter()函數(shù)根资,iter()是python的內置函數(shù)。iter()會返回一個定義了會返回一個定義了next()方法的迭代器對象同窘,它在容中逐個方法的迭代器對象玄帕,它在容中逐個方法的迭代器對象,它在容中逐個 訪問容器內元素想邦,next()也是python的內置函數(shù)裤纹。在沒有后續(xù)元素時,next()會拋出一個StopIter異常
(2)生成器(Generator)是創(chuàng)建迭代器的簡單而強大工具丧没。它們寫起來就像是正規(guī)的函數(shù)鹰椒,只在需要返回據(jù)時候使用 yield語句锡移。每次 next()被調用被調用 時,生成器會返回它脫離的位置(記憶語句最后一次執(zhí)行和所有數(shù)據(jù) 時漆际,生成器會返回它脫離的位置(記憶語句最后一次執(zhí)行和所有數(shù)據(jù) 時淆珊,生成器會返回它脫離的位置(記憶語句最后一次執(zhí)行和所有數(shù)據(jù)值)
區(qū)別:生成器能做到迭代的所有事區(qū)別:生成器能做到迭代的所有事,而且因為自動創(chuàng)建了
__iter__()
和 next()方法 奸汇,生成器顯得特別簡潔套蒂,而且生成器也是高效的 而且生成器也是高效的 而且生成器也是高效的 ,使用生成器表達式取代列茫蛹,使用生成器表達式取代列操刀,使用生成器表達式取代列解析可以同時節(jié)省內存。除了創(chuàng)建和保程序狀態(tài)的自動方法內存婴洼。除了創(chuàng)建和保程序狀態(tài)的自動方法 內存骨坑。除了創(chuàng)建和保程序狀態(tài)的自動方法內存。除了創(chuàng)建和保程序狀態(tài)的自動方法柬采,當發(fā)生器終結時 當發(fā)生器終結時當發(fā)生器終結時欢唾,還會自動拋出StopIteration異常。Yield的用法有點像return粉捻,但是它返回的是一個生成器礁遣。
3、線程肩刃、進程祟霍、協(xié)程
進程 是具有一定獨立功能的程序關于某個數(shù)據(jù)集合上的一次運行活動,進程是系統(tǒng)進行資源分配和調度的一個獨立單位。每個進程都有自己的獨立內存空間盈包,不同進程通過進程間通信來通信沸呐。由于進程比較重量,占據(jù)獨立的內存呢燥,所以上下文進程間的切換開銷(棧崭添、寄存器、虛擬內存叛氨、文件句柄等)比較大呼渣,但相對比較穩(wěn)定安全。
線程 是進程的一個實體寞埠,是CPU調度和分派的基本單位屁置,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統(tǒng)資源畸裳,只擁有一點在運行中必不可少的資源(如程序計數(shù)器缰犁,一組寄存器和棧淳地,但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源怖糊。線程間通信主要通過共享內存帅容,上下文切換很快,資源開銷較少伍伤,但相比進程不夠穩(wěn)定容易丟失數(shù)據(jù)并徘。
協(xié)程 是一種用戶態(tài)的輕量級線程,協(xié)程的調度完全由用戶控制扰魂。協(xié)程擁有自己的寄存器上下文和棧麦乞。協(xié)程調度切換時,將寄存器上下文和棧保存到其他地方劝评,在切回來的時候姐直,恢復先前保存的寄存器上下文和棧,直接操作棧則基本沒有內核切換的開銷蒋畜,可以不加鎖的訪問全局變量声畏,所以上下文的切換非常快姻成。
4插龄、什么是裝飾器?
裝飾器 是一個很著名的設計模式科展,經常被用于有切面需求的場景均牢,較為經典的有插入日志、性能測試才睹、事務處理等徘跪。裝飾器是解決這類問題的絕佳設計,有了裝飾器琅攘,我們就可以抽離出大量函數(shù)中與函數(shù)功能本身無關的雷同代碼并繼續(xù)重用真椿。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能乎澄。
裝飾器(decorator)里引入通用功能處理:引入日志突硝、函數(shù)執(zhí)行時間統(tǒng)計、執(zhí)行函數(shù)前預備處理置济、執(zhí)行函數(shù)后清理功能解恰、權限校驗等場景、緩存浙于。
舉個例子:
from time import ctime, sleep
def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.__name__, ctime()))
return func()
return wrappedfunc
@timefun
def foo():
print("I am foo")
foo()
sleep(2)
foo()
5护盈、談談你對同步異步阻塞非阻塞理解
所謂同步,就是在發(fā)出一個功能調用時羞酗,在沒有得到結果之前腐宋,該調用就不返回。按照這個定義,其實絕大多數(shù)函數(shù)都是同步調用(例如sin, isdigit等)胸竞。但是一般而言欺嗤,我們在說同步、異步的時候卫枝,特指那些需要其他部件協(xié)作或者需要一定時間完成的任務煎饼。最常見的例子就是 SendMessage。該函數(shù)發(fā)送一個消息給某個窗口校赤,在對方處理完消息之前吆玖,這個函數(shù)不返回。當對方處理完畢以后马篮,該函數(shù)才把消息處理函數(shù)所返回的 LRESULT值返回給調用者沾乘。
異步的概念和同步相對。當一個異步過程調用發(fā)出后浑测,調用者不能立刻得到結果意鲸。實際處理這個調用的部件在完成后,通過狀態(tài)尽爆、通知和回調來通知調用者怎顾。以CAsycSocket類為例(注意,CSocket從CAsyncSocket派生漱贱,但是起功能已經由異步轉化為同步)槐雾,當一個客戶端通過調用 Connect函數(shù)發(fā)出一個連接請求后,調用者線程立刻可以朝下運行幅狮。當連接真正建立起來以后募强,socket底層會發(fā)送一個消息通知該對象。這里提到執(zhí)行部件和調用者通過三種途徑返回結果:狀態(tài)崇摄、通知和回調擎值。可以使用哪一種依賴于執(zhí)行部件的實現(xiàn)逐抑,除非執(zhí)行部件提供多種選擇鸠儿,否則不受調用者控制。如果執(zhí)行部件用狀態(tài)來通知厕氨,那么調用者就需要每隔一定時間檢查一次进每,效率就很低(有些初學多線程編程的人,總喜歡用一個循環(huán)去檢查某個變量的值命斧,這其實是一種很嚴重的錯誤)田晚。如果是使用通知的方式,效率則很高国葬,因為執(zhí)行部件幾乎不需要做額外的操作贤徒。至于回調函數(shù)芹壕,其實和通知沒太多區(qū)別。
阻塞調用:指調用結果返回之前接奈,當前線程會被掛起踢涌。函數(shù)只有在得到結果之后才會返回。有人也許會把阻塞調用和同步調用等同起來鲫趁,實際上他是不同的斯嚎。對于同步調用來說利虫,很多時候當前線程還是激活的挨厚,只是從邏輯上當前函數(shù)沒有返回而已。例如糠惫,我們在CSocket中調用Receive函數(shù)疫剃,如果緩沖區(qū)中沒有數(shù)據(jù),這個函數(shù)就會一直等待硼讽,直到有數(shù)據(jù)才返回巢价。而此時,當前線程還會繼續(xù)處理各種各樣的消息固阁。如果主窗口和調用函數(shù)在同一個線程中壤躲,除非你在特殊的界面操作函數(shù)中調用,其實主界面還是應該可以刷新备燃。socket接收數(shù)據(jù)的另外一個函數(shù)recv則是一個阻塞調用的例子碉克。當socket工作在阻塞模式的時候,如果沒有數(shù)據(jù)的情況下調用該函數(shù)并齐,則當前線程就會被掛起漏麦,直到有數(shù)據(jù)為止。
非阻塞和阻塞的概念相對應况褪,指在不能立刻得到結果之前撕贞,該函數(shù)不會阻塞當前線程,而會立刻返回测垛。
對象的阻塞模式和阻塞函數(shù)調用捏膨。對象是否處于阻塞模式和函數(shù)是不是阻塞調用有很強的相關性,但是并不是一一對應的食侮。阻塞對象上可以有非阻塞的調用方式脊奋,我們可以通過一定的API去輪詢狀態(tài),在適當?shù)臅r候調用阻塞函數(shù)疙描,就可以避免阻塞诚隙。而對于非阻塞對象,調用特殊的函數(shù)也可以進入阻塞調用起胰。函數(shù)select就是這樣的一個例子久又。
6巫延、GIL對多線程的影響?
GIL的全稱是Global Interpreter Lock(全局解釋器鎖)地消,來源是python設計之初的考慮炉峰,為了數(shù)據(jù)安全所做的決定。每個CPU在同一時間只能執(zhí)行一個線程(在單核CPU下的多線程其實都只是并發(fā)脉执,不是并行疼阔,并發(fā)和并行從宏觀上來講都是同時處理多路請求的概念。但并發(fā)和并行又有區(qū)別半夷,并行是指兩個或者多個事件在同一時刻發(fā)生婆廊;而并發(fā)是指兩個或多個事件在同一時間間隔內發(fā)生。)
在Python多線程下巫橄,每個線程的執(zhí)行方式:
- 獲取GIL
- 執(zhí)行代碼直到sleep或者是python虛擬機將其掛起淘邻。
- 釋放GIL
可見,某個線程想要執(zhí)行湘换,必須先拿到GIL宾舅,我們可以把GIL看作是“通行證”,并且在一個python進程中彩倚,GIL只有一個筹我。拿不到通行證的線程,就不允許進入CPU執(zhí)行帆离。
在Python2.x里蔬蕊,GIL的釋放邏輯是當前線程遇見IO操作或者ticks計數(shù)達到100(ticks可以看作是Python自身的一個計數(shù)器,專門做用于GIL盯质,每次釋放后歸零袁串,這個計數(shù)可以通過 sys.setcheckinterval 來調整),進行釋放呼巷。而每次釋放GIL鎖囱修,線程進行鎖競爭、切換線程王悍,會消耗資源破镰。并且由于GIL鎖存在,python里一個進程永遠只能同時執(zhí)行一個線程(拿到GIL的線程才能執(zhí)行)压储。
IO密集型代碼(文件處理鲜漩、網絡爬蟲等),多線程能夠有效提升效率(單線程下有IO操作會進行IO等待集惋,造成不必要的時間浪費孕似,而開啟多線程能在線程A等待時,自動切換到線程B刮刑,可以不浪費CPU的資源喉祭,從而能提升程序執(zhí)行效率)养渴,所以多線程對IO密集型代碼比較友好。
7泛烙、python中的反射理卑?
python中反射的核心本質其實就是利用字符串的形式去對象(模塊)中操作(查找/獲取/刪除/添加)成員,一種基于字符串的事件驅動蔽氨。
希望能對你有所幫助藐唠。
哈哈哈哈,點個贊鹉究,關個注宇立?