今天的分享內容大致以下:html
一. 面試java
1. 什麼是面試python
2. 優秀的面試linux
二. Python綜述c++
1. Python設計哲學及版本變遷web
2. Python發展示狀及其餘語言使用場景面試
3. GIL算法
4. 內存管理和垃圾回收數據庫
5. 面試示例編程
3、併發並行
1. 進程
2. 線程
3. 協程
4. 併發編程
1、 面試
面:當面/面談/面聊, 試:考試,當前社會上各大企業和公司招人環節中最重要的一道流程關卡;目前面試已經衍生了多種操做形式:直面、電面、視頻面、在線coding;
一輪面試的過程當中,面試官期待什麼呢?面試又但願找到什麼樣的人呢?
...
面試官經過面試找到技能能力符合崗位預期、綜合素質(價值觀、協做、溝通、邏輯思惟等)優秀的候選人;
2. 優秀的面試
瞭解了面試官的出發點後,站在應聘者的角度,咱們又怎樣去看待呢?一輪優秀的面試過程是怎麼樣的呢?---優秀的面試應該是「可以最大化向面試官展現本身的技術能力和綜合素質符合所應聘的崗位」,候選人本人是面試過程當中的主人翁,面試過程當中應該要學會如下幾點:
1). 控場:應聘者自己是面試過程當中的主角,若是能無形中大致控制整個面試過程的流程走向,將其朝向預期的方向發展,通常也就離成功不遠了。大多數公司單輪面試時間會在20-60分鐘左右(少於20分鐘基本但願不大,大於1個小時的屬於高級崗位或者面試過程當中涉及到算法編程相關),面試官問的問題越多,碰到應聘者知識盲區的可能性也就越大,因此若是在保證質量的狀況下,最大化的讓面試官問到本身熟悉的領域對於大多數應聘者而言是須要思考和準備的;---忌一問一答或卡殼沉默
2). 亮點:面試過程當中最好能在部分問題的回答上突出本身的亮點,何爲亮點,即在必定程度上答案或者思路超出面試官對應聘者自己的期待;給予面試官深入的記憶點,這些記憶點會無形中淡化當輪面試中候選人發揮很差的部分,不少時候會決定者應聘者的面試的成敗;該部分主要依靠應聘者面試前的素材積累和麪試過程當中的語言技巧;
如何突出亮點呢?這邊提一個思路,從時空線的角度去整理;
時間線:問題點的前世此生將來;
空間線:問題點當前相關的技術;
面試中能夠不會,但不能不知道:不會和不知道是有區別的,不會是正常的,IT領域技術很是普遍,一我的的精力有限,不可能十八班武藝樣樣精通;但一些應聘領域常見的技術概念不知道則是不可取的,這可能會讓面試官產生懷疑:應聘者以前是否常常閉門造車,不怎麼關注當前領域業界的發展,候選人可能之後上升發展的空間可塑性有限等等;
2、Python綜述
接下來說面試過程當中的第一個部分--Python語言綜述;你們來到這邊都選擇了Python做爲本身工做的第一門語言,是出於什麼緣由呢?
在面試的過程當中,有時候會被問到,你怎麼看待Python,什麼情景下用Python,Python和其餘語言有什麼區別等等相似的問題,那咱們怎麼回答比較好呢?下面我將帶你們過一些Python知識點,你們在聽的過程當中能夠思考下怎麼在回答中將這些內容在面試回答中展示出來;
要想深刻的去理解Python這門語言,咱們須要瞭解Python的設計哲學,Python做者Guido Van Rossum是出於什麼原則來設計Python體系的呢?這點你們打開Python交互式模式,輸入import this
Beautiful is better than ugly. 優美勝於醜陋
Explicit is better than implicit. 明瞭勝於晦澀
Simple is better than complex. 簡單賽過複雜
Complex is better than complicated. 複雜賽過凌亂
Flat is better than nested. 扁平勝於嵌套
Sparse is better than dense. 間隔勝於緊湊
Readability counts. 可讀性很重要
(你們可能有些人英語不太好,但不要緊,直接Ctrl+C百度Google翻譯一下)其中最重要的設計哲學「簡單、明確、優雅」,Python做爲一種高級開發語言,封裝了大量的底層操做,極大的簡化開發編程的難度,同時在在美觀優雅也有本身獨特的追求,如裝飾器等;
1991年,第一個Python版本發佈,2000年,第一個Python穩定版本2.7發佈,2008年,Python3發佈;2020年,Python2將再也不維護;目前市場上主要以Python2.7和Python3.x爲主;其中Python2到Python3語法有較大變化;
因爲歷史緣由,當前市場上很多公司項目仍然是基於Python2.7.x開發,面試官有時會會問到面試者「Python3有哪些變化,和Python2有什麼不一樣?」,Python3的詳細變化有不少,咱們每一個人腦容量有限,並不須要所有都記下來,記憶中其中關鍵的幾條便可,如如下幾個方面:
1)Print用法
2)int和long,Python3中int至關於Python2中的int+long,即int不存在4字節數字溢出;
3)byte和str,Python3中對字符串編碼作了優化,只有byteL類型和str類型;
4)函數註釋新特性;
5)range至關於xrange,使用了迭代器進行循環迭代;
示例代碼以下:
# coding=utf-8 """ author = jamon """ if __name__ == "__main__": import sys sys.path.append("../") ''' def run_on_python27(): """ Python27 代碼示例 :return: """ print "老男孩" ''' def run_on_python3(): """ Python3 代碼示例 :return: None """ print("老男孩") a = "老男孩" b = a.encode("utf-8") c = b.decode("utf-8") print("a is {}, b is {}, c is {}".format(type(a), type(b), type(c))) def python3_new_feature(a: "first param", b: "第二個參數", c: float = 10) -> int: print("函數註釋新特性:", a, b, c) return 0 if __name__ == "__main__": run_on_python3() python3_new_feature("jiayou", "ok", ["test"]) print(python3_new_feature.__annotations__)
2. Python發展示狀及其餘語言使用場景
Python是一種腳本解釋性語言,相對於C/C++等傳統編程語言,會存在必定的性能損失,在一些特定的業務場景下,cpu密集型的高併發任務如複雜度較高的算法、反序列化等,能夠針對該部分具體邏輯改用C++編寫程三方庫,而後使用Python進行調用,同時發揮Python簡單低成本易維護和C++高性能優點;
Python當前在IT行業的工做主要分爲如下幾個部分:
a. web後臺開發
b. 遊戲後臺開發
c. 全棧開發
d. 爬蟲開發
e。測試開發
f. 運維開發
g. 其餘,如人工智能、數據分析等;
3. GIL(Global Interpreter Lock) 全局解釋鎖
面試過程當中常常會被問到「Python多線程有用過嗎?」 「Python的GIL是什麼?」等等此類問題,其實考點都是GIL鎖機制問題;
1991年Rossum設計Python時,當時世界上尚無多核處理器的存在,出於簡化CPython實現,更加容易的提供多線程支持,GIL應運而生,Python自己多線程因爲GIL的存在,能夠理解爲僞多線程,當使用默認的CPython做爲解釋器時,python多線程大多時候並不能坐到真正的並行,難以發揮多核多處理器的所有性能;
Python的GIL之因此會影響多線程性能,是由於在多線程的狀況下,只有當線程得到了一個全局鎖的時候,那麼該線程的代碼才能運行,而全局鎖只有一個,因此使用python多線程,在同一時刻只有一個線程在運行;
而GIL鎖的釋放時機有兩種狀況:
1)線程開始IO操做時,會先釋放GIL;
2)計算任務時,解釋器每隔100次opcode(可經過dis.dis()查看)或15ms釋放GIL;
下面將測試Python在多線程和單線程小的效率對比,代碼以下:
# coding=utf-8 """ author = jamon 參考博客:https://www.cnblogs.com/SuKiWX/p/8804974.html """ if __name__ == "__main__": import sys sys.path.append("../") from threading import Thread import time def my_counter(): i = 0 for _ in range(100000000): i = i + 1 return True def single_thread(): """ 單線程測試 :return: """ thread_array = {} start_time = time.time() for tid in range(2): t = Thread(target=my_counter) t.start() t.join() end_time = time.time() print("Total time: {}".format(end_time - start_time)) def multi_thread(): """ 多線程測試 :return: """ thread_array = {} start_time = time.time() for tid in range(2): t = Thread(target=my_counter) t.start() thread_array[tid] = t for i in range(2): thread_array[i].join() end_time = time.time() print("Total time: {}".format(end_time - start_time)) if __name__ == "__main__": single_thread() multi_thread()
小結:
Python的多線程在多核處理器上,只對IO密集型計算產生正面效果,而當其中至少有一個CPU密集型任務線程存在,則多線程的效率因爲GIL的存在將大幅降低;
如何避免GIL帶來的消極影響:
1)用multiprocessing代替thread,多進程方式每一個進程都有本身獨立的GIL,進程之間不會發生GIL爭搶;
2)用其餘的解析器,GIL只存在於Python默認的CPython解析器,當使用JPython、IronPython等其餘解析器時可避免GIL問題,但同時也失去了不少C語言有用模塊的機會;
4. 內存管理和垃圾回收
部分Python面試在深度這塊可能會問到「Python會不會存在內存泄露?」「Python內存是如何管理的」等諸如此類的問題,由於在具體的企業項目開發過程當中,隨着用戶規模的快速增加和業務邏輯的越發複雜,代碼缺陷和內存回收不善可能會引起內存性能瓶頸;
1)對象存儲:Python裏面萬物皆對象,全部的對象都會在內存中開闢一塊空間進行存儲,對象的內存地址能夠經過id()查看,對於整數和較小的字符,Python會緩存對象,不會建立多個相同對象;容器對象,存儲的其餘對象,僅僅是對象的引用,並非對象自己;
2)對象回收:一個對象會記錄自身被引用的個數,每增長一個引用計數+1,減小一個引用計數-1;注意當對象被做爲參數傳遞給函數時,引用計數會+2,由於函數調用時內部有兩個屬性引用;查看引用計數sys.getrefcount,當對象間出現相互循環引用時,此時對象將不能經過引用計數器進行銷燬。循環引用代碼見下圖:
分代回收: Python裏面將對象回收分爲三代,默認一個對象建立出來後,處於0代,經歷過必定的檢測次數後,依然存活,則遷移到下一代;垃圾回收的順序爲:
0代垃圾回收必定次數,會觸發0代和1代回收;
1代垃圾回收必定次數,會觸發0代、1代和2代回收;
gc.get_threshold()查看垃圾回收機制觸發條件和回收條件;
gc.set_threshold(700, 10,10), 設置垃圾回收機制條件,700指新增對象數-消亡對象數>=700時觸發垃圾檢測;第一個10只10次0代檢測後觸發一次1代檢測,第二個10指10次1代檢測後觸發2代檢測;
循環引用通常有兩種解決方法:
手動回收垃圾:gc.collect(),參考示例代碼
弱引用:weakref.ref
import gc import objgraph import sys import weakref def quote_demo(): class Person: pass p_xxx = Person() # 1 print(sys.getrefcount(p_xxx)) def log(obj): print(sys.getrefcount(obj)) log(p_xxx) p2 = p_xxx print(sys.getrefcount(p_xxx)) del p2 print(sys.getrefcount(p_xxx)) def circle_quote(): # 循環引用 class Dog: pass class Person(): pass p = Person() d = Dog() print(objgraph.count("Person")) print(objgraph.count("Dog")) p.pet = d d.master = p # 刪除 p, d以後, 對應的對象是否被釋放掉 del p del d print(objgraph.count("Person")) print(objgraph.count("Dog")) def solve_cirecle_quote(): # 1. 定義了兩個類 class Person: def __del__(self): print("Person對象, 被釋放了") pass class Dog: def __del__(self): print("Dog對象, 被釋放了") pass p = Person() d = Dog() p.pet = d d.master = p p.pet = None # 強制置 None del p del d gc.collect() print(objgraph.count("Person")) print(objgraph.count("Dog")) def sovle_circle_quote_with_weak_ref(): # 1. 定義了兩個類 class Person: def __del__(self): print("Person對象, 被釋放了") pass class Dog: def __del__(self): print("Dog對象, 被釋放了") pass p = Person() d = Dog() p.pet = d d.master = weakref.ref(p) del p del d gc.collect() print(objgraph.count("Person")) print(objgraph.count("Dog"))
回答思路:
時間線:
1991年,第一個穩定的Python版本;
2000年,Python2.7穩定版本發佈;
2008年,Python3發佈;
2020年,Python2再也不維護;
空間線:
Python設計哲學;
Python2、3特性;
和其餘編程語言(如c++)對比;
語言選型考慮因素;
思路串聯:設計哲學(Python本質特性)-> 如何選型(正面回答,取其精華) -> 埋下一個問題引子
示例答案:Python自1991年Rossum編寫發佈出第一個版本以來,便一直遵循着其設計哲學」簡單、明確、優雅「,設計哲學的根本出發點就決定了Python這門語言的編程開發的易用性和工做高效性,一樣的業務需求實現,可能傳統編程語言C++程序猿須要1周工期,而Python程序猿頗有可能三天不到就能完成,並且潛在隱藏的問題會少不少,由於Python自己目前有很是龐大的開源第三方庫,同時封裝了不少複雜的語言底層操做如內存分配與釋放,指針的相關操做等;
在具體的項目實踐過程當中,開發語言的選型須要考慮到幾個方面:項目業務自己的特色適合哪一種語言、公司歷史的技術棧和人員技術儲備傾向於哪一種語言、選型的語言當前領域內的生態體系和發展前景(好比是否不在維護);若是項目非計算密集型項目,其中對於算法性能等要求不是很是很是高,相對而言是業務功能和流程邏輯較爲複雜,此時Python語言就自然具有很大的優點,碰到其中少部分算法等計算性能瓶頸的地方能夠用c++等語言重寫,而後Python調用,這樣能夠兼顧Python開發低成本和C++高性能兩方面的有點;
具體選用Python後,新項目推薦使用python3,2008年Python3發佈後,十幾年來Python3生態圈三方庫已經很是完備和齊全,而官方已宣佈Python2在2020年將再也不維護,另外Python3自己性能也相較Python2有必定的提高;
回答思路2:
時間線:
截止2014年,哈佛、麻省理工、伯克利、卡內基等美國頂尖高校將Python做爲教學語言;
2018年開始,Python雄踞各大年度最佳編程語言排行榜榜首(IEEE, TIOBE)
空間線:
Python特性:動態、解釋、腳本、跨平臺...
解釋器:cpython,jpython,ipython,jit
Python2,3特性
思路串聯:Python特性(解釋、動態、腳本)-> 當前發展 -> 解釋器及性能優化 -> 埋下一個問題引子
示例答案2:Python語言和C++, Java等其餘編譯型語言不同,它是一種動態解釋型腳本語言,代碼在執行時會一行一行的解釋成CPU能理解的機器碼。同時它又是跨平臺的,能夠容許在windows,linux,mac等系統上,一樣的程序邏輯,可能C語言須要1000行代碼,java有100行,而Python實現可能只須要20行,這極大程度上提高了企業的項目開發效率。
記得以前看到一篇報道說,到2014年爲止,哈佛、麻省理工、伯克利等頂尖高校都已經使用Python做爲教學語言,而最近這一兩年來Python也屢次被各大機構評爲年度最佳編程語言。對於企業項目後臺開發而言,不是說必定須要使用Python開發,但至少應該是一個首選考慮項,固然Python自己從根本上來講性能是比不上C/C++這些編譯型語言,但如今語言自己的性能差距在實際開發的過程當中,相對業務功能合理性設計、代碼編寫架構質量等等,語言底層自己形成的性能損失愈來愈能夠忽略不計;針對於一些特定的功能模塊,Python當前也出現了pypy,JIT等大幅提升Python程序運行效率的相關技術,可以知足大多數功能需求業務場景。
具體選用Python後,新項目推薦使用python3,2008年Python3發佈後,十幾年來Python3生態圈三方庫已經很是完備和齊全,而官方已宣佈Python2在2020年將再也不維護,另外Python3自己性能也相較Python2有必定的提高;
回答思路3:
時間線:
20世紀60年代,UNIX誕生,貝爾實驗室發明B語言(過於簡單,數據無類型)
1972年,C語言誕生(面向過程),重寫UNIX;
1995年,Java出現;(面向對象)
2000年,第一個穩定的Python2版本發佈;
空間線:
語言的本質
Python行業發展(人工智能、雲計算、大數據...)
Python開源生態圈
Python2,3特性
思路串聯:語言進化 -> 語言本質 -> Python當前發展(應用產業及開源生態圈)-> 留下一個問題引子(此思路不說Python缺陷,留下兩個下一問題引子)
示例答案3:恩...這個問題我是這麼看的,上世紀60年Unix誕生時,貝爾實驗室是使用的B語言,解決了面向機器的彙編語言極其複雜問題,而後到72年,面向過程的C語言出現,再到95年Java誕生,面向對象的思想極大的提高了程序猿的開發效率。2000年第一個穩定的Python2版本,20年來其簡單高效的特質大大下降了研發人員的學習和開發成本;
編程語言的本質是人與機器溝通的工具,將人類但願機器作的事翻譯成機器自己可以理解的指令;語言發展進化的歷史也已經代表,越符合人類自身思惟邏輯及習慣的編程語言將越受到大衆歡迎。目前從雲端、客戶端,到物聯網終端,python應用無處不在,同時也是人工智能首先的編程語言(Python在在人工智能上的優點至今無人可以撼動)。Python當前也已經具有了很是完備豐富的開源三方生態圈(好比web框架tornado,sanic, 運維監控zabbix,遊戲引擎firefly等等不勝枚舉)。對於大多數企業新後臺項目開發,我的傾向於推薦Python做爲首選語言。
具體選用Python後,新項目推薦使用python3,2008年Python3發佈後,十幾年來Python3生態圈三方庫已經很是完備和齊全,而官方已宣佈Python2在2020年將再也不維護,另外Python3自己性能也相較Python2有必定的提高;
3、併發並行
併發相關的問題在面試中是一個很容易被問到的模塊,好比」協程是什麼?怎麼理解協程?和線程進程有什麼區別...「 接下來我將給你們梳理一下進程、線程、協程等併發相關的知識考點。
1. 進程:
你們前面的課程學過進程相關的一些概念,那什麼是進程呢?
進程是系統進行資源分配和調度的基本單位,是操做系統動態執行的基本單元,fork多進程,子進程將複製父進程的數據空間及堆棧,此時有涉及到一個考點--copy on write(寫時複製),即只有在子進程中有更改相應段的行爲時,纔會將父進程的內容複製給子進程;子進程在複製父進程變量時,複製的是邏輯地址,父子進程相同的邏輯地址在內存中實際對應的物理地址是不同的;
什麼是邏輯地址和物理地址呢?
邏輯地址是cpu生成的地址,包括頁號、頁偏移,能夠理解爲相對地址的概念,和基址結合,能夠肯定其在內存中對應的物理單元地址;而物理地址指內存單元看到的地址;
進程複製和切換的代價是比較高的,Python語言中多進程比較適合CPU密集型任務,此類任務多進程的方式可以最大化利用到當前多核處理器的並行優點;但同時進程的頻繁建立和刪除也消耗了過多的計算機資源;
2.線程
線程是操做系統進行運算調度的最小單位,是進程的實際運做單位。而線程又分爲內核線程和用戶線程。內核線程又稱輕量級線程,由操做系統內核建立和撤銷;用戶線程是在語言這一層級進行處理,它的建立、銷燬和調度不須要內核支持;
多任務程序設計中多線程的方式相較多進程的優點主要有幾點:一是無需複製申請新的資源,全部子線程和父線程會共享資源;二是線程間通訊速度遠遠快於進程間通訊,效率更高;
3. 協程:
當前多線程的狀況下,線程間的切換通常是根據時間片或者執行的代碼數達到必定的閾值後進行切換,雖然線程間的切換代價相較進程已經小了不少,但當線程較多且生存週期較長時,頻繁的線程切換代價累計起來漸漸的難以忽略,此時一種多任務運做模式應運而生。
協程,又稱微線程,也即纖程。協程和線程同樣都是一段子程序,但協程的特色是一個線程在執行,只有當該子程序內部發生中斷或阻塞時,纔會交出線程的執行權交給其餘子程序,在適當的時候再返回來接着執行。與多線程相比,協程的優點主要有兩點:一是省去了大量線程切換的開銷,不須要頻繁作線程切換;二是因爲是單線程執行,此時共享資源便不須要加鎖,執行效率比多進程高不少;
固然爲了利用多核處理器的優點,生產環境中使用協程通常推薦多進程+協程的方式,既充分利用多核,又能夠發揮協程高效的方式;Python對協程的支持用generaotr的yield能夠必定程度上實現;
4. 併發編程:
在生產環境中有些時候咱們遇到這樣的場景:如數據庫有作分表操做n張表,需求是須要查詢特定的數據,而這些數據實際卻分佈於n張表中,查詢的結果須要統一返回給調用者,調用者自己是不知道有分表查詢的操做,那麼怎樣高效完成這一操做呢?
傳統的實現方式時串行執行,即循環查詢每一張表,依次合併全部查詢的結果;這種方式隨着循環次數的增多效率將直線降低;此時實際上咱們能夠多任務併發的方式解決這類問題;
示例代碼以下:
# coding=utf-8 import math from multiprocessing import Pool import time def parallel_compute(call_func, param_list=[], process_num=10, need_return=True): """ 批量並行調用某一函數, 每次調用傳遞參數不一樣, 返回結果進行合併; 執行的函數中有DB操做時,注意須要在函數內部從新實例化DB鏈接實例,不然易出現未知錯誤 :param call_func: 待進行的函數 :param param_list: [(), (), ...], 參數長度(併發的進程數) :param process_num: int, 同時並行的子進程數, 默認最大爲10 :param need_return: 是否須要返回計算結果 :return: { 1: result2, 2: result2, 3:... } """ if not param_list: return s_time = time.time() results = {} task_num = len(param_list) loop_num = int(math.ceil(task_num/float(process_num))) for t in range(0, loop_num): real_num = len(param_list[t*process_num:(t+1)*process_num]) pool = Pool(processes=real_num) for i in range(0, real_num): results[t*process_num+i] = pool.apply_async(call_func, param_list[t*process_num+i]) pool.close() pool.join() e_time = time.time() print("parallel_compute {0} {1} tasks took {2}s" .format(str(call_func.__name__), process_num, e_time - s_time)) if not need_return: return for k, v in results.items(): results[k] = v.get() return results
def test(id, name, gold):
time.sleep(1)
print("test ", id, game, gold)
return id * 10
if __name__ == "__main__":
params_list = []
for i in range(20):
params_list.append([i, "hello_{0}".format(i), i*100])
result = parallel_compute(test, params_list, need_return=1, process_num=10)
print("\nresult=", result)
做業3:協程怎麼理解?/進程線程有什麼區別?/高併發怎麼實現?...