python大致

1.1Python 語言基礎

1.語言特色web

2.語法基礎面試

3.高級特性redis

1.2算法與數據結構

1.經常使用算法和數據結構算法

2.分析時間和空間複雜度數據庫

3.實現常見數據結構和算法編程

1.3編程範式

1.面向對象編程後端

2.經常使用設計模式設計模式

3.函數式編程緩存

1.4操做系統

1.經常使用 Linux安全

2.進程和線程

3.內存管理

1.5網絡編程

1.經常使用協議 TCP、IP、HTTP

2.Socket 編程基礎

3.Python 併發庫

1.6數據庫

1.MySQL 數據庫、索引優化

2.關係型和 NoSQL 的使用場景

3.Redis 緩存(經常使用的數據類型以及使用場景,底層實現瞭解會更好)

1.7Python Web框架

1.經常使用框架的對比,使用 Restful

2.WSGI 原理

3.Web 安全的問題

1.8系統設計

1.設計原則,如何分析

2.後端系統經常使用的組件(緩存、數據庫、消息隊列等等)

3.技術選型和實現(短網址服務、Feed 流系統)

1.9技術以外的軟實力

1.學習能力

2.業務理解能力,溝通交流能力

3.心態

2.0小擴展-STAR模型

在生活中描述一件事情或者是在面試中描述項目經驗,如何讓咱們的語言更加有條理,邏輯性?能夠採用以下的模型進行梳理。

情境(situation) 什麼狀況下發生的
任務(task) 你是如何明確你的任務的
行動(action) 採起了什麼樣的行動
結果(result) 結果怎麼樣?學到了什麼?

 

2.技術棧詳解

2.1 Python 語言基礎

2.1.1 Python 語言特性

Python 是動態強類型語言,不少人都誤認爲是弱類型語言,實際上是錯誤的。

動態是指在運行期肯定類型(靜態則是在編譯期肯定類型)。強類型指的是在沒有強制類型轉化前,不容許兩種不一樣類型的變量相互操做(也就是不會發生隱式類型轉換)。

2.1.2 Python 做爲後端語言的優缺點

爲何使用 Python ?

答:它是一門膠水語言,輪子多,應用普遍;語言靈活,生產力高,是一些創業公司以及外包項目節省時間的首選語言。可是在使用的時候,須要考慮到性能的問題,代碼維護問題,以及2和3版本的兼容問題。

2.1.3 Python 其餘的重要知識點

鴨子類型簡單介紹

曾有一個生動的例子來描述鴨子類型:當看到一隻鳥,若是它走起來像鴨子、叫起來像鴨子,游泳的時候也像鴨子,那麼咱們就稱這隻鳥是鴨子。它的關注點在對象的行爲,而不是類型。好比一些經常使用對象 file、StringIO、socket 都支持 read/write 方法,咱們能夠看作相似的對象 file like object;再舉個例子,在 Python 中實現了 __iter__ 魔法方法的對象均可以用 for 迭代。

什麼是 monkey patch ?

答:所謂的 monkey patch 就是運行時的屬性替換。好比咱們經常使用的一個併發庫 gevent ,須要將內置的 socket 修改成非阻塞。咱們在使用的時候,用到以下的代碼:

  1. from gevent import monkey

  2. # 打補丁,讓gevent框架識別耗時操做,好比:time.sleep,網絡請求延時

  3. monkey.patch_all()

什麼是自省?

答:自省就是在運行時判斷一個對象的類型的能力。咱們能夠經過 type、id和 isinstance 等方法獲取對象類型的信息。Inspect 模塊提供了更多獲取對象信息的函數。

什麼是列表和字典推導式?

列表生成式:

  1. my_list = [i for i in range(10) if i % 2 == 0]

字典推導式:

  1. dict1 = {k: v for k, v in zip(a, b)}

特殊的狀況:將列表推導式的方括號修改成小括號的時候,會返回一個生成器。

2.1.4 Python 之禪

The Zen of Python 即是著名的Python 之禪,它是由 Tim Peters 編寫的關於 Python 編程的準則,咱們可使用下面的代碼進行查看:

  1. import this

咱們在編程的過程當中,若是拿不許的時候能夠進行一個參考。

2.2 Python2 和 Python3 的差別

2.2.1 Python2/3 差別

Python3 中作了一些改進,咱們須要瞭解。好比 print 成爲了函數;還有編碼的問題,Python3 中再也不有 Unicode 對象,默認 str 就是 Unicode;除法也有所變化,好比 Python3 除法返回的是浮點數。

Python2 裏面是沒有類型申明的,Python3 中咱們能夠添加一個類型註解(type hint),幫助 IDE 實現類型提示以及類型檢查(mypy)。Python3 中優化的 super() 方便直接調用父類函數。Python3 中還有一些高級的解包操做,以下面示例:

  1. a, b, *rest = range(10)

上面會將0賦值給 a,將1賦值給 b,而後將剩下的賦值給 rest。

類型檢查示例:

  1. In [2]: def fuction(name: str): return 'hello' + name

  2. In [3]: fuction('Ethan')

  3. Out[3]: 'helloEthan'

Python3 限定關鍵字參數。也就是函數在傳參的時候,咱們能夠經過關鍵字參數方式,指定參數名傳參,避免參數太多時候搞混。

Python3 中從新拋出異常不會丟失棧信息,方便咱們去排錯(在 Python2 中若是在一個異常中 raise 一個異常,原來的異常就會丟失,Python3 中支持 raise from,保留異常棧信息)。

Python3 中一切都是返回迭代器,好比 range/zip/map/dict.value/etc. are all iterators。

2.2.2 Python3 新增

1.yield from 連接子生成器

2.asyncio 內置庫, async、await 原生協程支持異步編程

3.新的內置庫 enum(枚舉),mock(單測時用),asyncio, ipaddress (處理ip地址)等等。

2.2.3 Python3 改進

1.生成的 pyc 文件統一放到 __pycache__文件夾下。

2.一些內置庫的修改。如 urllib,selector(支持select、epoll等Linux底層的一些封裝,方便咱們統一作一些接口,實現異步IO) 等。

3.一些性能的優化,好比 dict。

2.2.4一些兼容二、3的工具

1. six 模塊。

2. 2to3 等工具轉換代碼。(腳本工具,將 Python2 轉換爲 Python3 代碼)

3. __future__模塊。在 Python2 中使用 Python3 的函數功能可參照以下代碼:

  1. from __future__ import print_fuction

2.3 Python 函數

2.3.1 Python 如何傳遞參數?

答:Python 其實不是引用傳遞也不是值傳遞,而是共享傳參(函數形參得到實參中各個引用的副本)。簡單的理解一下:

咱們在每一次傳遞參數的時候,形參和實參都指向同一個對象,這樣就叫作對象傳遞,既不是拷貝了一個值,也不是直接去操做這塊內存,可是它的結果有兩個。對於可變對象來講,咱們直接去修改它,對於不可變對象來講,表現就好像 copy 了一個值,而後去修改新的值。

不可變對象好像是傳值,可變對象好像是傳引用。可是實際是不一樣的。

2.3.2 Python 可變/不可變對象

1.可變對象:bool、int、float、tuple、str

2.不可變對象:list、set、dict

可變對象做爲默認參數的時候,注意默認參數只計算一次。

2.3.3 Python 中 *args 和 **kwargs

函數傳遞中,他們處理可變參數。若是使用 *args那麼會將全部的參數打包成一個 tuple 對象。 **kwargs 則是將全部的關鍵字參數打包成一個 dict 對象。

2.4 Python 異常機制

2.4.1什麼是 Python 的異常?

答:異常就是一種錯誤處理機制。全部的異常都繼承自 BaseException 。舉幾個和系統相關的異常:SystemExit、KeyboardInterrupt、GeneratorExit(生成器退出的異常)。還有一個異常的基類就是 Exception。

2.4.2使用異常的常見場景

答:網絡請求(超時、鏈接錯誤);資源訪問(權限問題、資源不存在);代碼邏輯(越界訪問、KeyError等)。

2.4.3處理異常

  1. try:

  2. # 可能會拋出異常的代碼

  3. except (Exception1, Exception2) as e:

  4. # 異常處理代碼

  5. else:

  6. # 異常沒有發生時代碼邏輯

  7. finally

  8. # 不管異常有沒有發生都會執行的代碼,通常處理資源的關閉和釋放。

2.4.4如何自定義異常

1.繼承自 Exception 實現自定義異常(想一想爲何不是 BaseException)

能夠經過查看異常的等級信息,發現若是繼承自頂級父類,那麼一些經常使用的異常也沒有了,本身須要定義的異常就太多太多,耗費時間。

2.能夠給異常加上一些附加信息。

3.一般都是處理一些和業務相關的特定異常(raise MyException)

2.5 Python 性能分析與優化

Python 做爲一門腳本語言來講,它的性能一直被詬病。而且因爲存在一個臭名昭著的 GIL 致使沒有辦法充分利用多核,這都限制了 Python 的性能。

2.5.1什麼是 CPython GIL?

GIL (Global Interpreter Lock)

1.CPython 解釋器的內存管理並非線程安全的,存在多個線程時,有可能會出現同時修改同一對象,這樣容易出現問題。

2.爲了保護多線程狀況下對 Python 對象的訪問,CPython 使用了簡單的鎖機制避免多個線程同時執行字節碼。

缺陷即是沒有辦法同時利用 CPU 的多核,只有一個線程執行字節碼。對於 CPU 密集型的程序來講,影響會比較大。

2.5.2 GIL 的影響

限制了程序的多核執行。

1.同一個時間只能有一個線程執行字節碼

2.CPU 密集型程序難以利用多核優點。

3.IO 期間會釋放 GIL ,對 IO 密集型程序影響不大。

2.5.3如何規避 GIL 的影響

1.CPU 密集型可使用多進程 + 進程池的方式充分的利用多核。

2.IO 密集型可使用多線程或者是協程。

3.使用 cython 擴展(將 Python 程序轉化成 C 代碼的一個擴展)。

2.5.4 GIL 的實現

CPython 中才會有 GIL ,其餘的解釋器是沒有的。底層的代碼邏輯是設置一個ticker,每執行多少個字節碼的時候,去檢查當前是否有全局解釋器鎖,若是有那麼執行函數釋放,讓其餘的線程去執行;若是沒有,就從新獲取鎖。通俗一點就是每隔一段時間,就會嘗試去釋放當前線程的鎖,讓其餘線程獲取鎖並去執行。

2.5.5爲何有了 GIL 以後,還要關注線程安全?

Python中什麼操做纔是原子的?一步到位執行完的。

1.一個操做若是是一個字節碼指令能夠完成的就是原子的。

2.原子的是能夠保證線程安全的,非原子操做不是線程安全的。

3.使用 dis 操做來分析字節碼。

  1. import dis

  2.  

  3. def update_list(l):

  4. l[0] = 1

  5.  

  6. dis.dis(update_list)

2.5.6如何剖析程序性能

使用各類 profile 工具(內置或第三方)

1.遵循二八定律,其實大部分的時間耗時在少許的代碼上。

2.經過內置的 profile 和 cprofile 等工具衡量程序的運行時間。

3.對於 web 應用來講,使用 pyflame(uber開源) 的火焰圖工具分析產品的性能。

2.5.7服務端性能優化措施

web應用通常語言不會成爲瓶頸。能夠採用以下的一些優化措施:

1.數據結構和算法優化。

2.數據庫層:索引優化、慢查詢消除、批量操做減小IO、NoSQL的使用。

3.網絡IO:批量操做, pipline 操做減小 IO。

4.緩存:使用內存數據庫 redis、memcached 等。以此抗一些併發比較高的請求。

5.使用異步的框架或者庫如 asyncio 和 celery。

6.對於併發相關的一些請求使用 gevent 協程或者多線程。

2.6 Python 生成器與協程

2.6.1什麼是生成器

Generator

1.生成器就是能夠生成值的函數。

2.當一個函數裏有了 yield 關鍵字就成了生成器。

3.生成器能夠掛起執行而且保持當前執行的狀態。

2.6.2基於生成器的協程

Python3 以前沒有原生協程,只有基於生成器的協程。

1.pep 342(Coroutines via Enhanced Generators)加強生成器功能。

2.生成器能夠經過 yield 暫停執行和產出數據。

3.同時支持 send() 向生成器發送數據和 throw() 向生成器拋異常。

示例:

  1. def coro():

  2. # yield 關鍵字在 = 右邊做爲表達式,能夠被send值

  3. hello = yield 'hello'

  4. yield hello

  5. c = coro()

  6. # 輸出 `hello`,這裏調用next產出第一個值 `hello`,以後函數暫停

  7. print(next(c))

  8. # 再次調用 send 發送值,此時hello變量賦值爲 `world`,而後yield 產出hello變量的值 `world`

  9. print(c.send('world'))

  10. # 以後協程結束,後續再send值會拋出異常StopIteration

2.6.3協程的注意點

1.協程須要使用 send(None) 或者 next(coroutine) 來 『預激』(prime) 才能啓動。

2.在 yield 處協程會暫停執行。

3.單獨的 yield value 會產出值給對方調用

4.能夠經過 coroutine.send(value) 來給協程發送值,發送的值會賦值給 yield 表達式左邊的變量 value=yield

5.協程執行完成以後(沒有遇到下一個 yield 語句)會拋出 StopIteration 異常。

2.6.4協程裝飾器

避免每次都要用 send 預激它。

  1. from functools import wraps

  2. def coroutine(func):

  3. # 這樣就不須要每次都用send(None)啓動了

  4. # 裝飾器:向前執行到第一個 `yield` 表達式,預激`func`

  5. @wraps(func)

  6. def primer(*args,**kwargs):

  7. gen = func(*args,**kwargs)

  8. next(gen)

  9. return gen

  10. return primer

2.6.5Python3 原生協程

Python3.5 引入 async/await 支持原生協程(native coroutine)

2.7單元測試

2.7.1什麼是單元測試

Unit Testing

1.針對程序模塊進行正確性檢驗。

2.一個函數,一個類進行驗證。

3.自底向上保證程序正確性。

2.7.2爲何寫單元測試

三無代碼不可取(無文檔、無註釋、無單測)

1.保證代碼邏輯的正確性(甚至有些採用測試驅動開發(TDD))

2.單測影響設計,易測的代碼每每是高內聚低耦合的。

3.迴歸測試,防止改一處整個服務不可用。

2.7.3單元測試相關的庫

1.nose/pytest 較爲經常使用

2.mock 模塊用來模擬替換網絡請求等

3.coverage 統計測試覆蓋率

如何設計測試用例:(等價類劃分):

1.正常值功能測試。

2.邊界值(好比最大最小,最左最右值)

3.異常值(好比None,空值,非法值)

2.8重點知識

2.8.1 Python 深拷貝與淺拷貝

淺拷貝:對於不可變對象至關於引用賦值;淺拷貝對於可變對象拷貝時只拷貝第一層引用。

深拷貝:對於不可變對象一樣至關於引用賦值;對於可變對象會逐層進行拷貝。

Python 中淺拷貝的方式:copy 模塊的 copy 方法;對象自己的 copy 方法;工廠方法;切片(只對列表有效)。

工廠方法就是直接使用 list 等方法進行修改。

Python 中默認使用的就是淺拷貝方式。

2.8.2小結

1.不可變對象在賦值時會開闢新空間

2.可變對象在賦值時,修改一個引用的值,另外一個引用也會發生改變。

3.深淺拷貝對不可變對象拷貝時,不開闢新的空間,至關於賦值操做。

4.淺拷貝在拷貝時,只拷貝頂層中的引用,若是元素是可變對象,而且被修改,那麼拷貝的對象也會發生變化。

5.深拷貝在拷貝時,會逐層進行拷貝,直到全部的引用都是不可變對象爲止。

6.Python 中有多種方式實現淺拷貝,copy 模塊的 copy 函數,對象的 copy 函數,工廠方法,切片等。

7.大多數狀況下,編寫程序時,都是使用淺拷貝,除非有特定的需求。

8.淺拷貝的優勢:拷貝速度快,佔用空間少,拷貝效率高。

相關文章
相關標籤/搜索