1. python中下劃線是什麼意思
下劃線是一個匿名變數
2. 詳解Python中的__new__、__init__、__call__三個特殊方法
__new__: 對象的創建,是一個靜態方法,第一個參數是cls。(想想也是,不可能是self,對象還沒創建,哪來的self)
__init__ : 對象的初始化, 是一個實例方法,第一個參數是self。
__call__ : 對象可call,注意不是類,是對象。
先有創建,才有初始化。即先__new__,而後__init__。
上面說的不好理解,看例子。
1.對於__new__
可以看到,輸出來是一個Bar對象。
__new__方法在類定義中不是必須寫的,如果沒定義,默認會調用object.__new__去創建一個對象。如果定義了,就是override,可以custom創建對象的行為。
聰明的讀者可能想到,既然__new__可以custom對象的創建,那我在這里做一下手腳,每次創建對象都返回同一個,那不就是單例模式了嗎?沒錯,就是這樣。可以觀摩《飄逸的python - 單例模式亂彈》
定義單例模式時,因為自定義的__new__重載了父類的__new__,所以要自己顯式調用父類的__new__,即object.__new__(cls, *args, **kwargs),或者用super()。,不然就不是extend原來的實例了,而是替換原來的實例。
2.對於__init__
使用Python寫過面向對象的代碼的同學,可能對 __init__ 方法已經非常熟悉了,__init__ 方法通常用在初始化一個類實例的時候。例如:
這樣便是__init__最普通的用法了。但__init__其實不是實例化一個類的時候第一個被調用 的方法。當使用 Persion(name, age) 這樣的表達式來實例化一個類時,最先被調用的方法 其實是 __new__ 方法。
3.對於__call__
對象通過提供__call__(slef, [,*args [,**kwargs]])方法可以模擬函數的行為,如果一個對象x提供了該方法,就可以像函數一樣使用它,也就是說x(arg1, arg2...) 等同於調用x.__call__(self, arg1, arg2) 。模擬函數的對象可以用於創建防函數(functor) 或代理(proxy).
總結,在Python中,類的行為就是這樣,__new__、__init__、__call__等方法不是必須寫的,會默認調用,如果自己定義了,就是override,可以custom。既然override了,通常也會顯式調用進行補償以達到extend的目的。
這也是為什麼會出現"明明定義def _init__(self, *args, **kwargs),對象怎麼不進行初始化"這種看起來詭異的行為。(注,這里_init__少寫了個下劃線,因為__init__不是必須寫的,所以這里不會報錯,而是當做一個新的方法_init__)
3. python sort()用法
Python中的sort()方法用於數組排序,下面以實例形式對此加以詳細說明:
一、基本形式
列表有自己的sort方法,其對列表進行原址排序,既然是原址排序,那顯然元組不可能擁有這種方法,因為元組是不可修改的。
x=[4,6,2,1,7,9]x.sort()
printx#[1,2,4,6,7,9]
如果需要一個排序好的副本,同時保持原有列表不變,怎麼實現呢
x=[4,6,2,1,7,9]
y=x[:]
y.sort()
printy#[1,2,4,6,7,9]
printx#[4,6,2,1,7,9]
注意:y = x[:] 通過分片操作將列表x的元素全部拷貝給y,如果簡單的把x賦值給y:y = x,y和x還是指向同一個列表,並沒有產生新的副本。
另一種獲取已排序的列表副本的方法是使用sorted函數:
x=[4,6,2,1,7,9]
y=sorted(x)
printy#[1,2,4,6,7,9]
printx#[4,6,2,1,7,9]
sorted返回一個有序的副本,並且類型總是列表,如下:
printsorted('Python')#['P','h','n','o','t','y']
二、自定義比較函數
可以定義自己的比較函數,然後通過參數傳遞給sort方法:
defcomp(x,y):
ifx<y:
return1
elifx>y:
return-1
else:
return0
nums=[3,2,8,0,1]
nums.sort(comp)
printnums#降序排序[8,3,2,1,0]
nums.sort(cmp)#調用內建函數cmp,升序排序
printnums#降序排序[0,1,2,3,8]
三、可選參數
sort方法還有兩個可選參數:key和reverse
1、key在使用時必須提供一個排序過程總調用的函數:
x=['mmm','mm','mm','m']
x.sort(key=len)
printx#['m','mm','mm','mmm']
2、reverse實現降序排序,需要提供一個布爾值:
y=[3,2,8,0,1]
y.sort(reverse=True)
printy#[8,3,2,1,0]
4. Python筆記:Python裝飾器
裝飾器是通過裝飾器函數修改原函數的一些功能而不需要修改原函數,在很多場景可以用到它,比如① 執行某個測試用例之前,判斷是否需要登錄或者執行某些特定操作;② 統計某個函數的執行時間;③ 判斷輸入合法性等。合理使用裝飾器可以極大地提高程序的可讀性以及運行效率。本文將介紹Python裝飾器的使用方法。
python裝飾器可以定義如下:
輸出:
python解釋器將test_decorator函數作為參數傳遞給my_decorator函數,並指向了內部函數 wrapper(),內部函數 wrapper() 又會調用原函數 test_decorator(),所以decorator()的執行會先列印'this is wrapper',然後列印'hello world', test_decorator()執行完成後,列印 'bye' ,*args和**kwargs,表示接受任意數量和類型的參數。
裝飾器 my_decorator() 把真正需要執行的函數 test_decorator() 包裹在其中,並且改變了它的行為,但是原函數 test_decorator() 不變。
一般使用如下形式使用裝飾器:
@my_decorator就相當於 decorator = my_decorator(test_decorator) 語句。
內置裝飾器@functools.wrap可用於保留原函數的元信息(將原函數的元信息,拷貝到對應的裝飾器函數里)。先來看看沒有使用functools的情況:
輸出:
從上面的輸出可以看出test_decorator() 函數被裝飾以後元信息被wrapper() 函數取代了,可以使用@functools.wrap裝飾器保留原函數的元信息:
輸出:
裝飾器可以接受自定義參數。比如定義一個參數來設置裝飾器內部函數的執行次數:
輸出:
Python 支持多個裝飾器嵌套:
裝飾的過程:
順序從里到外:
test_decorator('hello world') 執行順序和裝飾的過程相反。
輸出:
類也可以作為裝飾器,類裝飾器主要依賴__call__()方法,是python中所有能被調用的對象具有的內置方法(python魔術方法),每當調用一個類的實例時,__call__()就會被執行一次。
下面的類裝飾器實現統計函數執行次數:
輸出:
下面介紹兩種裝飾器使用場景
統計函數執行所花費的時間
輸出:
在使用某些web服務時,需要先判斷用戶是否登錄,如果沒有登錄就跳轉到登錄頁面或者提示用戶登錄:
--THE END--