Python-常見面試題彙總參考:Python-面向對象編程總結

目錄html

基礎與特性前端

列舉布爾值爲False的常見值?python

Python遞歸的最大層數?web

print([i%2 for i in range(10)])和print((i%2 for i in range(10)))的結果?sql

簡述解釋型語言和編譯型語言?數據庫

解釋器種類及特色django

字符串格式化有哪幾種?編程

簡述字符串駐留機制?json

什麼是反射,舉個例子flask

Python自省

Python做用域

函數及函數式編程

函數調用時參數傳遞方式?

什麼是閉包?

什麼是lambda函數?

裝飾器

裝飾器的做用和功能?

迭代器、生成器

迭代器和生成器的區別是什麼?

拷貝

深拷貝和淺拷貝有什麼區別?

線程、進程與協程

如何在Python中實現多線程?

協程

面向對象

Python的元類?

靜態方法,類方法

類變量和實例變量

Python中單下劃線和雙下劃線

重載

__new__和__init__的區別

文件

read,readline和readlines

內存管理

Python垃圾回收機制?

Python是如何進行內存管理的?

WEB

什麼是wsgi,uwsgi,uWSGI?

Django、Flask的對比?

Django

django請求的生命週期?

列舉django的內置組件?

簡述什麼是FBV和CBV?

django中csrf防護的實現機制

Django自己提供了runserver,爲何不能用來部署?

跨域問題如何解決?

參考


基礎與特性

列舉布爾值爲False的常見值?

0,[],(),{},'',Flase,None

Python遞歸的最大層數?

998

def fun(num):
    if num == 0:
        return 0
    else:
        return fun(num - 1)


if __name__ == '__main__':
    print(fun(998))

結果

RecursionError: maximum recursion depth exceeded in comparison

print([i%2 for i in range(10)])和print((i%2 for i in range(10)))的結果?

>>> print([i%2 for i in range(10)])
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
>>> print((i%2 for i in range(10)))
<generator object <genexpr> at 0x00000283335C7F48>

一個是列表,一個是生成器/迭代器

簡述解釋型語言和編譯型語言?

-編譯型(須要編譯器,至關於用谷歌翻譯):編譯型語言執行速度快,不依賴語言環境運行,跨平臺差,如C/C++執行速度快,調試麻煩

-解釋型(須要解釋器,至關於同聲傳譯):解釋型跨平臺好,一份代碼,處處使用,缺點是執行速度慢,依賴解釋器運行,如Python、JAVA執行速度慢,調試方便

解釋器種類及特色

    CPython是使用最廣且被的Python解釋器。
    IPython是基於CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所加強,可是執行Python代碼的功能和CPython是徹底同樣的。CPython用>>>做爲提示符,而IPython用In[序號]:做爲提示符。
    PyPy是另外一個Python解釋器,它的目標是執行速度。PyPy採用JIT技術,對Python代碼進行動態編譯(注意不是解釋),因此能夠顯著提升Python代碼的執行速度。絕大部分Python代碼均可以在PyPy下運行,可是PyPy和CPython有一些是不一樣的,這就致使相同的Python代碼在兩種解釋器下執行可能會有不一樣的結果。若是你的代碼要放到PyPy下執行,就須要瞭解PyPy和CPython的不一樣點。
    Jython是運行在Java平臺上的Python解釋器,能夠直接把Python代碼編譯成Java字節碼執行。
    IronPython和Jython相似,只不過IronPython是運行在微軟.Net平臺上的Python解釋器,能夠直接把Python代碼編譯成.Net的字節碼。

字符串格式化有哪幾種?

佔位符

>>> 'hello,%s' % 'world'
'hello,world'

format

>>> 'hello,{}'.format('world')
'hello,world'

f-string

>>> f'hello,{"world"}'
'hello,world'

簡述字符串駐留機制?

對於短字符串,將其照值給多個不一樣的對象時,內存中只有一個副本,多個對象共享該副本。長字符串不遵照駐留機制。
駐留適用範圍:由數字,字符和下劃線組成的python標識符以及整數[-5,256]。

>>> s1='hello_world'
>>> s2='hello_world'
>>> id(s1)
2762526059824
>>> id(s2)
2762526059824 

>>> s1='hello_world'*10000
>>> s2='hello_world'*10000
>>> id(s1)
2762523045808
>>> id(s2)
2762523155872 

什麼是反射,舉個例子

反射是把字符串映射到實例的變量或者實例的方法而後能夠去執行調用、修改等操做。利用如下四個內置函數:

  • getattr 獲取指定字符串名稱的對象屬性
  • setattr 爲對象設置一個對象
  • hasattr 判斷對象是否有對應的對象(字符串)
  • delattr 刪除指定屬性

例如:

>>> s2='hello_world'
>>> getattr(s2,'split')('_')
['hello', 'world']

Python自省

運行時得到對象的類型等,內置函數dir、type、isinstance等,利用了反射機制。

Python做用域

本地做用域(Local)→當前做用域被嵌入的本地做用域(Enclosing locals)→全局/模塊做用域(Global)→內置做用域(Built-in)

函數及函數式編程

函數調用時參數傳遞方式?

函數傳參是引用傳遞,函數外一直不變,須要區分對象是否可變。對於不可變類型,能夠經過返回修改後的引用來改變它(指向其餘地方)。

函數基礎總結與內置函數

什麼是閉包?

在一個函數內部的函數,具體來講:

  • 必須有一個內嵌函數
  • 內嵌函數必須引用外部函數中的變量
  • 外部函數的返回值必須是內嵌函數

什麼是lambda函數?

lambda函數也叫匿名函數,該函數能夠包含任意數量的參數,但只能有一個執行操做的語句

裝飾器

裝飾器的做用和功能?

一句話:爲已經存在的對象添加額外的功能

  • 引入日誌
  • 函數執行時間統計
  • 執行函數棧預備處理
  • 執行函數後的清理功能
  • 權限校驗
  • 緩存

迭代器、生成器

迭代器和生成器的區別是什麼?

一、共同點

生成器是一種特殊的迭代器。

二、不一樣點

a、語法上:

生成器是經過函數的形式中調用 yield 或()的形式建立的,自動建立了__iter__()和next()方法,顯得特別簡潔,也是高效的。

迭代器能夠經過iter()內置函數建立。

b、用法上:

生成器在調用next()函數或for循環中,全部過程被執行,且返回值,須要的時候才返回,生成器表達式比列表生成式更節省內存

迭代器在調用next()函數或for循環中,全部值被返回,沒有其餘過程或動做。

拷貝

深拷貝和淺拷貝有什麼區別?

在建立新實例類型時使用淺拷貝,並保留在新實例中複製的值。淺拷貝用於複製引用指針,就像複製值同樣。這些引用指向原始對象,而且在類的任何成員中所作的更改也將影響它的原始副本。淺拷貝容許更快地執行程序,它取決於所使用的數據的大小。

深拷貝用於存儲已複製的值。深拷貝不會將引用指針複製到對象。它引用一個對象,並存儲一些其餘對象指向的新對象。原始副本中所作的更改不會影響使用該對象的任何其餘副本。因爲爲每一個被調用的對象建立了某些副本,所以深拷貝會使程序的執行速度變慢。

淺拷貝拷貝數據集合的第一層數據,深拷貝拷貝數據集合的全部層。

線程、進程與協程

如何在Python中實現多線程?

Python有一個多線程庫,可是用多線程來加速代碼的效果並非那麼的好,

Python有一個名爲Global Interpreter Lock(GIL)的結構。GIL確保每次只能執行一個「線程」。一個線程獲取GIL執行相關操做,而後將GIL傳遞到下一個線程。

雖然看起來程序被多線程並行執行,但它們實際上只是輪流使用相同的CPU核心

全部這些GIL傳遞都增長了執行的開銷。這意味着多線程並不能讓程序運行的更快。

協程

簡單點說協程是進程和線程的升級版,進程和線程都面臨着內核態和用戶態的切換問題而耗費許多切換時間,而協程就是用戶本身控制切換的時機,再也不須要陷入系統的內核態。

Python裏最多見的yield就是協程的思想!

面向對象

Python的元類?

先定義metaclass,就能夠建立類,最後建立實例。

因此,metaclass容許你建立類或者修改類。換句話說,你能夠把類當作是metaclass建立出來的「實例」。它指示Python解釋器在建立MyList時,要經過ListMetaclass.__new__()來建立。

ORM就是一個典型的例子。

靜態方法,類方法

\ 實例方法 類方法 靜態方法
a = A() a.foo(x) a.class_foo(x) a.static_foo(x)
A 不可用 A.class_foo(x) A.static_foo(x)

實例方法,類沒法調用。類方法和靜態方法類和實例均可以調用。A.class_foo(x)能夠理解爲class_foo(A,x),a.class_foo(x)能夠理解爲class_foo(a,x),a會轉化爲A。靜態方法和類沒有太大關係。

類變量和實例變量

類變量是全部實例共享的

實例變量是實例單獨擁有的

Python中單下劃線和雙下劃線

雙下劃線"__變量或函數__",是Python內部爲了防止和用戶自定義命名衝突。

雙下劃線"__變量或函數",解析器用_classname__foo來代替這個名字,以區別和其餘類相同的命名,它沒法直接像公有成員同樣隨便訪問,經過對象名._類名__xxx這樣的方式能夠訪問。

單下劃線"_變量或函數",是指定變量私有,不能經過from module import *導入,其餘地方和公有同樣。

參考:Python-面向對象編程總結

重載

  1. 可變參數類型。
  2. 可變參數個數。

基本的設計原則:僅僅當兩個函數除了參數類型和參數個數不一樣之外,其功能是徹底相同的,此時才使用函數重載。

__new____init__的區別

  1. __new__是一個靜態方法,__init__是一個實例方法
  2. __new__方法會返回一個建立的實例,而__init__什麼都不返回。
  3. 只有在__new__返回一個cls的實例時後面的__init__才能被調用。
  4. 建立一個新實例時調用__new__,初始化一個實例時用__init__

利用__new__可實現單例模式

文件

read,readline和readlines

  • read 讀取整個文件
  • readline 讀取下一行,使用生成器方法
  • readlines 讀取整個文件到一個迭代器以供咱們遍歷
內存管理

Python垃圾回收機制?

垃圾回收:

Python不像C++,Java等語言同樣,他們能夠不用事先聲明變量類型而直接對變量進行賦值。對python語言來說,對象的類型和內存都是在運行時肯定的。這也是爲何咱們稱python語言爲動態類型的緣由(這裏咱們把動態類型語言能夠簡單的歸結爲對變量內存地址的分配是在運行時自動判斷變量類型並對變量進行賦值)。

引用計數:

Python採用了相似windows內核對象同樣的方式來對內存進行管理。每個對象,都維護這一個對指向該對象的引用的計數。當變量被綁定在一個對象上的時候,該變量的引用計數就是1,,系統會自動維護這些標籤,並定時掃描,當某標籤的引用計數變爲0的時候,該對象就會被回收。

標記-清除:

「標記-清除」不改動真實的引用計數,而是將集合中對象的引用計數複製一份副本,改動該對象引用的副本。對於副本作任何的改動,都不會影響到對象生命走起的維護。基本思路是先按需分配,等到沒有空閒內存的時候從寄存器和程序棧上的引用出發遍歷以對象爲節點、以引用爲邊構成的圖,把全部能夠訪問到的對象打上標記,而後清掃一遍內存空間,把全部沒標記的對象釋放。
分代回收:

將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每個集合就成爲一個「代」,垃圾收集的頻率隨着「代」的存活時間的增大而減少。也就是說,活得越長的對象,就越不多是垃圾,就應該減小對它的垃圾收集頻率。那麼如何來衡量這個存活時間:一般是利用幾回垃圾收集動做來衡量,若是一個對象通過的垃圾收集次數越多,能夠得出:該對象存活時間就越長。

舉例: 當某些內存塊M通過了3次垃圾收集的清洗以後還存活時,咱們就將內存塊M劃到一個集合A中去,而新分配的內存都劃分到集合B中去。當垃圾收集開始工做時,大多數狀況都只對集合B進行垃圾回收,而對集合A進行垃圾回收要隔至關長一段時間後才進行,這就使得垃圾收集機制須要處理的內存少了,效率天然就提升了。

Python是如何進行內存管理的?

內存池機制:

    python的內存機制成金字塔形:

    第-1,-2層主要有操做系統進行操做;

    第0層是C中的malloc,free等內存分配和釋放函數進行操做;

    第1層和第2層是內存池,有python的接口函數PyMem_Malloc函數實現,當對象小於256字節時由該層直接分配內存;

    第三層是最上層,也就是咱們對python對象的直接操做;

在C中若是頻繁的調用malloc與free時,是會產生性能問題的,在加上頻繁的分配和釋放小塊的內存會產生內存碎片。

python在這裏主要乾的工做有:

若是請求分配的內存在1~256字節之間就使用本身的內存管理系統,不然直接使用malloc。

這裏仍是會調用malloc分配內存,但每次回分配一塊大小爲256字節的大塊內存。

經由內存池登記的內存到最後仍是會回收到內存池,並不會調用C的free釋放掉,以便下次使用。對於簡單的python對象,例如數值、字符串、元組(tuple不容許被更改)採用的是複製的方式(深拷貝),也就是說當講另外一個變量B賦值給變量A時,雖然A和B的內存空間仍然相同,可是當A的值發生變化時,會從新給A分配空間,A和B的地址變得再也不相同。

WEB

什麼是wsgi,uwsgi,uWSGI?

WSGI:

web服務器網關接口,是一套協議。用於接收用戶請求並將請求進行初次封裝,而後將請求交給web框架。

實現wsgi協議的模塊:wsgiref,本質上就是編寫一socket服務端,用於接收用戶請求(django)

werkzeug:本質上就是編寫一個socket服務端,用於接收用戶請求(flask)

uwsgi:與WSGI同樣是一種通訊協議,它是uWSGI服務器的獨佔協議,用於定義傳輸信息的類型。

uWSGI:是一個web服務器,實現了WSGI的協議,uWSGI協議,http協議

Django、Flask的對比?

一、 Django走的大而全的方向,開發效率高。它的MTV框架,自帶的ORM,admin後臺管理,自帶的sqlite數據庫和開發測試用的服務器,給開發者提升了超高的開發效率。 重量級web框架,功能齊全,提供一站式解決的思路,能讓開發者不用在選擇上花費大量時間。

自帶ORM和模板引擎,支持jinja等非官方模板引擎。

自帶ORM使Django和關係型數據庫耦合度高,若是要使用非關係型數據庫,須要使用第三方庫

自帶數據庫管理app

成熟,穩定,開發效率高,相對於Flask,Django的總體封閉性比較好,適合作企業級網站的開發。python web框架的先驅,第三方庫豐富

二、 Flask 是輕量級的框架,自由,靈活,可擴展性強,核心基於Werkzeug WSGI工具 和jinja2 模板引擎

適用於作小網站以及web服務的API,開發大型網站無壓力,但架構須要本身設計

與關係型數據庫的結合不弱於Django,而與非關係型數據庫的結合遠遠優於Django

Django

django請求的生命週期?

  • 當用戶在瀏覽器中輸入url時,瀏覽器生成請求頭和請求體發給服務端,請求頭和請求體中包含瀏覽器的動做(action),這個動做一般爲Get或者Post
  • url通過Django中的wsgi,再通過Django的中間件,最後url到路由映射表,在路由中一條一條進行匹配,一旦其中一條匹配成功就執行對應的視圖函數,後面的路由就再也不繼續匹配了
  • 視圖函數根據客戶端的請求查詢相應的數據,返回給Django,而後Django把客戶端想要的數據返回
  • 客戶端瀏覽器接收到返回的數據,通過渲染後顯示給用戶

列舉django的內置組件?

  • .Admin是對model中對應的數據表進行CRUD提供的組件
  • .model組件:負責操做數據庫
  • .form組件:1.生成HTML代碼 2.數據有效性校驗 3校驗信息返回並展現
  • .ModelForm組件:用於數據庫操做,也可用於用戶請求的驗證

簡述什麼是FBV和CBV?

FBV和CBV本質是同樣的,基於函數的視圖叫作FBV,基於類的視圖叫作CBV
在python中使用CBV的優勢:

  • 提升了代碼的複用性,可使用面向對象的技術,例如Mixin(多繼承)
  • 能夠用不一樣的函數針對不一樣的HTTP方法處理,而不是經過不少if判斷,提升代碼可讀性

django中csrf防護的實現機制

  • 第一步:django第一次響應來自某個客戶端的請求時,後端隨機產生一個token值,把這個token保存在SESSION狀態中,同時,後端把這個token放到cookie中交給前端頁面
  • 第二步:下次前端須要發起請求的時候把這個token值加入到請求數據或者頭信息中,一塊兒傳給後端;Cookies:{csrf_token:xxxxx}
  • 第三步:後端校驗前端請求帶過來的token和SESSION裏的token是否一致。

Django自己提供了runserver,爲何不能用來部署?

  • 1.runserver方法是調試 Django 時常常用到的運行方式,它使用Django自帶的WSGI Server 運行,主要在測試和開發中使用,而且 runserver 開啓的方式也是單進程。
  • 2.uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http 等協議。注意uwsgi是一種通訊協議,而uWSGI是實現uwsgi協議和WSGI協議的 Web 服務器。uWSGI具備超快的性能、低內存佔用和多app管理等優勢,而且搭配着Nginx就是一個生產環境了,可以將用戶訪問請求與應用 app 隔離開,實現真正的部署 。相比來說,支持的併發量更高,方便管理多進程,發揮多核的優點,提高性能

跨域問題如何解決?

  • cors:安裝django-cors-headers
  • jsonp

不斷更新中...

相關文章
相關標籤/搜索