閱讀本文大約須要 8 分鐘。
原理:利用閉包,將目標函數外面再套一層函數,使得目標函數具備一個新的功能,而且不改變目標函數原有功能。 算法
實現方式:多線程
閉包閉包
def decorate(func): def wrapper(): print('新功能') func() return wrapper def func(): print('原有功能') f = decorate(func) f() # 結果爲: 新功能 原有功能
@ 語法糖app
def decorate01(func): def wrapper(): print('新功能') func() return wrapper @decorate01 def func01(): print("原有功能") func01() # 結果爲: 新功能 原有功能
類屬性至關於所有變量,全部由類建立出來的實例,均可以使用,而實例屬性至關於局部變量,只能由該實例本身使用,當類屬性與實例屬性命名同樣時,在調用該同名屬性時,會屏蔽掉類屬性,調用實例屬性,這點跟 LEGB 很像。函數
當經過實例對象來修改類屬性時,其實修改的並非類屬性,而是新建了一個跟類屬性名同樣的實例屬性。性能
Python 中將以兩個下劃線__
開頭,但不以兩個下劃線結尾的變量,認做爲私有屬性,Python 經過 name manage
算法,將該私有屬性的引用更改成_classname_reference
,用戶試圖調用該私有屬性時,會由於對象引用不同而找不到該屬性,故而實現了「屬性私有化」。spa
在獲取實例屬性時,通常採用定義一個實例方法的方式獲取屬性,避免直接對實例屬性進行操做,起到一個保護屬性的做用。線程
Python 至關於其餘靜態語言,能夠在代碼運行過程當中,改變變量的屬性。code
鴨子類型指的是 Python 不用定義變量類型,只要該變量像是什麼類型,那麼就認爲它就是什麼類型,咱們更多關注的是它的行爲,而不是它的類型。協程
實例都是由類建立出來,而類則是由元類建立出來。他們之間的關係至關於「奶奶-媽媽-孫子」。
示例:
class Myclass(): pass new = type('NewClass', (Myclass,), {'name': 'new'}) print(new) print(new.__mro__) # 查看該類的繼承狀況 # 結果爲 <class '__main__.NewClass'> (<class '__main__.NewClass'>, <class '__main__.Myclass'>, <class 'object'>)
具體點的內容能夠參考這篇問答:什麼是元類
@staticmethod 是爲類添加一個靜態方法
@classmethod 是爲類添加一個類方法
因爲 Python 的特性使得程序在運行過程當中,咱們能夠爲某個對象添加屬性、方法。
示例:
class Myclass: pass m = Myclass() # 爲實例動態添加一個屬性 m.name = 'new_atribute' def func(self): return 'new_function' # 爲實例動態添加一個方法 m.func = func print(m.name) print(m.__dict__) # 返回 m 的全部屬性,方法 # 結果爲 new_atribute new_function {'func': <function func at 0x7f9452be12f0>, 'name': 'new_atribute'} # 另一種動態添加方法 import types def func01(self): print('new_function01') # 實例 m 添加一個屬性 func,而這個屬性指向func()函數,故當調用 m.func 時,也就至關於調用了 func() 函數,間接實現了爲 m 添加方法 func()。 m.func = types.MethodType(func, m) print(m.func()) # 結果爲 new_function01
先介紹什麼是可迭代的Iterable
:任何可用於for
循環的都是可迭代的。也可使用collection
模塊下的isinstance(obj, Iterable)
來檢驗該對象是否可迭代。
示例:
from collections import Iterable print(isinstance('abc',Iterable)) print(isinstance(123,Iterable)) # 結果爲 True,False
迭代器
任何可使用next()
函數的都是迭代器,也可以使用iter()
函數將可迭代對象變爲迭代器。
示例:
from collections import Iterator itr = iter('abc') print(type(itr)) print(isinstance(itr, Iterator)) # 結果爲 Iterator,True
生成器
任何函數中含有yield
關鍵字的都是生成器,列表生成式中的[]
改成()
也是一個生成器。
實現方式
示例:
g = [i for i in range(10)] print(type(g)) # 結果爲 list g1 = (i for i in range(10)) print(type(g1)) # 結果爲 generator def func(): for i in range(10): yield i f = func() print(f) # 結果爲 <generator object func at 0x7f92f5294048>
生成器怎麼取值,何時結束
生成器能夠經過next(f)
、f.__next__()
和f.send()
三種方式來取值
示例:
def func01(): for i in range(10): yield i f = func() print(next(f)) print(f.__next__()) print(f.send('hahah')) # 結果爲 0 1 2
其中f.send()
能夠向生成器傳值,可是其第一次傳入的值默認爲None
。若是想要取出send('hahah')
裏傳入的值,則須要在生成器中添加接收的變量。
示例:
def func(): for i in range(10): # yield i temp = yield i print(temp) f = func() print(next(f)) print(f.__next__()) print(f.send('hahah')) # 結果爲 0 None 1 hahah 2
生成器裏的值被取完以後,或者中間遇到 return
關鍵字,就會退出,這三種方法有一個共同點:當生成器取完以後會拋出StopIteration
的錯誤。
而使用for
循環來取出生成器裏的值就不會拋出錯誤,這也是最被推薦的。
在生成一個包含不少數(百萬級別)的列表時,可是又只用獲得其中很小一部分的數時,使用列表生成式會極大的浪費內存,且不必定可以生成,由於受機器內存限制。
而使用生成器則否則,生成器只是在你須要的時候,纔會申請一塊內存,能夠邊取邊用,極大的下降了內存消耗。
生成器用的最多的地方在於「協程」。因爲基於 C 解釋器下的 Python 中含有一個 GIL 鎖,使得 Pyhon 的多線程是一個假性多線程,這也是爲何不少人說 Python 性能慢的緣由。
未寫完,下次更新補上。