目錄html
基礎與特性前端
列舉布爾值爲False的常見值?python
print([i%2 for i in range(10)])和print((i%2 for i in range(10)))的結果?sql
解釋器種類及特色django
簡述字符串駐留機制?json
什麼是反射,舉個例子flask
Django自己提供了runserver,爲何不能用來部署?
0,[],(),{},'',Flase,None
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)])
[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
反射是把字符串映射到實例的變量或者實例的方法而後能夠去執行調用、修改等操做。利用如下四個內置函數:
例如:
>>> s2='hello_world'
>>> getattr(s2,'split')('_')
['hello', 'world']
運行時得到對象的類型等,內置函數dir、type、isinstance等,利用了反射機制。
本地做用域(Local)→當前做用域被嵌入的本地做用域(Enclosing locals)→全局/模塊做用域(Global)→內置做用域(Built-in)
函數及函數式編程函數傳參是引用傳遞,函數外一直不變,須要區分對象是否可變。對於不可變類型,能夠經過返回修改後的引用來改變它(指向其餘地方)。
在一個函數內部的函數,具體來講:
lambda函數也叫匿名函數,該函數能夠包含任意數量的參數,但只能有一個執行操做的語句。
一句話:爲已經存在的對象添加額外的功能
一、共同點
生成器是一種特殊的迭代器。
二、不一樣點
a、語法上:
生成器是經過函數的形式中調用 yield 或()的形式建立的,自動建立了__iter__()和next()方法,顯得特別簡潔,也是高效的。
迭代器能夠經過iter()內置函數建立。
b、用法上:
生成器在調用next()函數或for循環中,全部過程被執行,且返回值,須要的時候才返回,生成器表達式比列表生成式更節省內存。
迭代器在調用next()函數或for循環中,全部值被返回,沒有其餘過程或動做。
在建立新實例類型時使用淺拷貝,並保留在新實例中複製的值。淺拷貝用於複製引用指針,就像複製值同樣。這些引用指向原始對象,而且在類的任何成員中所作的更改也將影響它的原始副本。淺拷貝容許更快地執行程序,它取決於所使用的數據的大小。
深拷貝用於存儲已複製的值。深拷貝不會將引用指針複製到對象。它引用一個對象,並存儲一些其餘對象指向的新對象。原始副本中所作的更改不會影響使用該對象的任何其餘副本。因爲爲每一個被調用的對象建立了某些副本,所以深拷貝會使程序的執行速度變慢。
淺拷貝拷貝數據集合的第一層數據,深拷貝拷貝數據集合的全部層。
線程、進程與協程Python有一個多線程庫,可是用多線程來加速代碼的效果並非那麼的好,
Python有一個名爲Global Interpreter Lock(GIL)的結構。GIL確保每次只能執行一個「線程」。一個線程獲取GIL執行相關操做,而後將GIL傳遞到下一個線程。
雖然看起來程序被多線程並行執行,但它們實際上只是輪流使用相同的CPU核心。
全部這些GIL傳遞都增長了執行的開銷。這意味着多線程並不能讓程序運行的更快。
簡單點說協程是進程和線程的升級版,進程和線程都面臨着內核態和用戶態的切換問題而耗費許多切換時間,而協程就是用戶本身控制切換的時機,再也不須要陷入系統的內核態。
Python裏最多見的yield就是協程的思想!
面向對象先定義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內部爲了防止和用戶自定義命名衝突。
雙下劃線"__變量或函數",解析器用_classname__foo
來代替這個名字,以區別和其餘類相同的命名,它沒法直接像公有成員同樣隨便訪問,經過對象名._類名__xxx這樣的方式能夠訪問。
單下劃線"_變量或函數",是指定變量私有,不能經過from module import *導入,其餘地方和公有同樣。
基本的設計原則:僅僅當兩個函數除了參數類型和參數個數不一樣之外,其功能是徹底相同的,此時才使用函數重載。
__new__
和__init__
的區別__new__
是一個靜態方法,而__init__
是一個實例方法。__new__
方法會返回一個建立的實例,而__init__
什麼都不返回。__new__
返回一個cls的實例時後面的__init__
才能被調用。__new__
,初始化一個實例時用__init__
。利用__new__可實現單例模式
文件垃圾回收:
Python不像C++,Java等語言同樣,他們能夠不用事先聲明變量類型而直接對變量進行賦值。對python語言來說,對象的類型和內存都是在運行時肯定的。這也是爲何咱們稱python語言爲動態類型的緣由(這裏咱們把動態類型語言能夠簡單的歸結爲對變量內存地址的分配是在運行時自動判斷變量類型並對變量進行賦值)。
引用計數:
Python採用了相似windows內核對象同樣的方式來對內存進行管理。每個對象,都維護這一個對指向該對象的引用的計數。當變量被綁定在一個對象上的時候,該變量的引用計數就是1,,系統會自動維護這些標籤,並定時掃描,當某標籤的引用計數變爲0的時候,該對象就會被回收。
標記-清除:
「標記-清除」不改動真實的引用計數,而是將集合中對象的引用計數複製一份副本,改動該對象引用的副本。對於副本作任何的改動,都不會影響到對象生命走起的維護。基本思路是先按需分配,等到沒有空閒內存的時候從寄存器和程序棧上的引用出發,遍歷以對象爲節點、以引用爲邊構成的圖,把全部能夠訪問到的對象打上標記,而後清掃一遍內存空間,把全部沒標記的對象釋放。
分代回收:
將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每個集合就成爲一個「代」,垃圾收集的頻率隨着「代」的存活時間的增大而減少。也就是說,活得越長的對象,就越不多是垃圾,就應該減小對它的垃圾收集頻率。那麼如何來衡量這個存活時間:一般是利用幾回垃圾收集動做來衡量,若是一個對象通過的垃圾收集次數越多,能夠得出:該對象存活時間就越長。
舉例: 當某些內存塊M通過了3次垃圾收集的清洗以後還存活時,咱們就將內存塊M劃到一個集合A中去,而新分配的內存都劃分到集合B中去。當垃圾收集開始工做時,大多數狀況都只對集合B進行垃圾回收,而對集合A進行垃圾回收要隔至關長一段時間後才進行,這就使得垃圾收集機制須要處理的內存少了,效率天然就提升了。
內存池機制:
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的地址變得再也不相同。
WEBWSGI:
web服務器網關接口,是一套協議。用於接收用戶請求並將請求進行初次封裝,而後將請求交給web框架。
實現wsgi協議的模塊:wsgiref,本質上就是編寫一socket服務端,用於接收用戶請求(django)
werkzeug:本質上就是編寫一個socket服務端,用於接收用戶請求(flask)
uwsgi:與WSGI同樣是一種通訊協議,它是uWSGI服務器的獨佔協議,用於定義傳輸信息的類型。
uWSGI:是一個web服務器,實現了WSGI的協議,uWSGI協議,http協議
一、 Django走的大而全的方向,開發效率高。它的MTV框架,自帶的ORM,admin後臺管理,自帶的sqlite數據庫和開發測試用的服務器,給開發者提升了超高的開發效率。 重量級web框架,功能齊全,提供一站式解決的思路,能讓開發者不用在選擇上花費大量時間。
自帶ORM和模板引擎,支持jinja等非官方模板引擎。
自帶ORM使Django和關係型數據庫耦合度高,若是要使用非關係型數據庫,須要使用第三方庫
自帶數據庫管理app
成熟,穩定,開發效率高,相對於Flask,Django的總體封閉性比較好,適合作企業級網站的開發。python web框架的先驅,第三方庫豐富
二、 Flask 是輕量級的框架,自由,靈活,可擴展性強,核心基於Werkzeug WSGI工具 和jinja2 模板引擎
適用於作小網站以及web服務的API,開發大型網站無壓力,但架構須要本身設計
與關係型數據庫的結合不弱於Django,而與非關係型數據庫的結合遠遠優於Django
FBV和CBV本質是同樣的,基於函數的視圖叫作FBV,基於類的視圖叫作CBV
在python中使用CBV的優勢:
不斷更新中...