對預設引數的理解
預設引數和關鍵字引數對應:預設引數是形參,關鍵字引數是實參。
呼叫函式的時候,如果沒有傳入該預設引數的值,就取預設引數的預設值,直白地說,就是你傳,就用你的;你不傳,我就用預設的。
def info(name,age=18):
# age = 18 就是預設引數
print("name is %s" %name)
print("age is %d" %age)
# 呼叫函式
info(name='jack') # 未給age傳引數,就去預設值age=18
# 輸出結果:name is jack age is 18
# 呼叫函式
info(name='jack',age=66) # 傳給關鍵字引數 則age=66
# 輸出結果:name is jack age is 66
裝飾器的理解
作用:寫**需要遵循開放封閉原則,它規定已經實現的功能**不允許被修改,但是可以被擴充套件。
當我們需要為一段已經寫好的**新增功能的時候,在不改變源**的情況下,加乙個裝飾器完成功能的新增功能。
例如:
(1)引入日誌
(2)函式執行時間統計
(3)執行函式之前的預備處理
(4)執行函式之後的清理功能
(5)許可權校驗等場景
(6)快取
裝飾器實現原理
1、先了解閉包
# 定義乙個函式
def test(number):
# 在函式內部再定義乙個函式,並且這個函式用到了外邊函式的變數
# 那麼將這個函式以及用到的一些變數稱之為閉包
def test_in(number_in):
print("in test_in函式,number_in is %d" %number_in)
return number + number_in
# 其實這裡返回的就是閉包的結果
return test_in
demo = test(3)
print(demo(2))
@函式名(python的語法糖)@test下面的函式作為test函式的引數
def test1(func):
# 驗證1
return func() + ''
# 這裡不帶()返回的是閉包的結果
def test2(func):
# 驗證2
return func() + ''
# 這裡不帶(),返回的是閉包的結果
@test1
@test2
def info():
return 'hello'
print(info())
# 返回結果
# hello
裝飾器原理分析
裝飾階段:將裝飾器裝飾的函式當做引數,傳給裝飾器,返回乙個閉包(這裡用到了閉包,外部的引數會傳遞給內部函式的引用,而不會被釋放),並且賦值給原函式名,使原函式名指向了這個閉包。而此時裝飾器的引數func指向原來的函式;
執行階段:呼叫原函式實際是呼叫的閉包,閉包在指向原函式前可以執行一段我們要加的邏輯。
裝飾器開始裝飾不是隨著執行函式時裝飾,而是在建立在對這個函式裝飾時就裝飾。
每裝飾乙個就建立乙個閉包。
裝飾問題,變數名指向問題
@test2
def info():
test2(func)的引數func,指向原來的函式info。
@test1
...test1(func)的引數func,指向@test2裝飾
test2(func)的引數func,指向原來的函式info
裝飾器引數(也可以是不定長引數)from time import ctime,sleep
# 這個裝飾器的作用是在函式開始之前列印開始時間
def timefun(func):
print("%s called at %s" %(func.__name__,ctime()))
print(a,b)
func(a,b)
@timefun
def foo(a,b):
print(a+b)
foo(3,5)
sleep(2)
foo(2,4)
# 執行結果
# foo called at tue apr 10 15:50:30 2018
# 3 5
# 8# foo called at tue apr 10 15:50:32 2018
# 2 4
# 6
類裝飾器(擴充套件)
類裝飾器其實是乙個介面約束,它必須接受乙個callable物件作為引數,然後返回乙個callable物件。在python中一般callable物件都是函式,但是也有例外。只要某個物件重寫了call() 方法,那麼物件就是callable的。
# 類裝飾器demo
class test(object):
def __init__(self,func):
print("---初始化---")
print("func name is %s" %func.__name__)
self.__func = func
def __call__(self):
print("---裝飾器的功能---")
self.__func()
# 說明:
# 1. 當使用test來裝作裝飾器對test函式進行裝飾的時候,首先會建立test的例項物件
# 並且會把test這個函式名當作引數傳遞到__init__方法中
# 即在__init__ 方法中的屬性__func指向了test指向的函式
# # 2. test指向了用test建立出來的例項物件
# # 3. 當在使用test()進行呼叫時,就相當於讓這個物件(),因此會呼叫這個物件的__call__方法
# 4. 為了能夠在__call__方法中呼叫原來test指向的函式體,所以在__init__方法中就需要
# 乙個例項屬性來儲存這個函式體的引用
# 所以才有了self.__func = func 這句**,從而在呼叫__call__方法中能夠呼叫到
# test之前的函式體
@test
def test():
print("---test---")
test()
showpy()
引數,裝飾器
引數 若函式中所實現的需求涉及到一些未知項參與運算 這些未知項需要函式的呼叫者來決定 此時,可以將未知項設定為引數.位置引數 必備引數 傳遞引數的順序與定義的順序有關,必須按照定義的順序來進行傳遞.傳遞引數的個數與引數的個數必須保持一致.關鍵字引數 指函式呼叫的時候,可以通過 鍵 值 的形式來加以指...
裝飾器三 裝飾器不帶引數
非固定引數接收傳入的實參,不論是多少都會接收。args,kwargs user status false def login func func是要傳入的函式的記憶體位址 def inner args,kwargs user alex password 123 global user status ...
裝飾器帶引數
裝飾器帶引數 帶引數的裝飾器是三層的 最外層的函式負責接受裝飾器引數 裡面的內容還是源裝飾器的內容 def outer a 第一層 負責接受引數的 defdecorate func 第二層 負責接受函式的 def wargs,kwargs 第三層 負責接受函式的引數 func wargs print...