最近想整一整數據分析,在看一本關於數據分析的書中提到了(1)if __name__ == '__main__' (2)列表解析式 (3)裝飾器。html
先簡單描述一下前兩點,再詳細解說Python初級的函數裝飾器。python
進入正題:app
1、if __name__ == '__main__' 函數
1 def printHello(): 2 print("Hello World!") 3 print(__name__) 4 if __name__ == '__main__': 5 printHello()
其輸出以下:測試
Hello World! __main__
由於此時這個文件是以主程序的方式運行的,故它的__name__爲__main__。spa
1 from name_main import printHello 2 printHello()
咱們只會獲得 printHello 運行一次的結果。這一次結果是 import 語句的效果,真正的 printHello 函數被 if 語句攔住了(由於它的__name__變成了本身的文件名而非__main__)。code
2、列表解析式htm
3、裝飾器對象
#直接裝飾@ def printname(func): #裝飾器:實質是一個函數,參數是須要裝飾的函數名(非函數調用) def wrapper(*args, **kwargs): #可變參數*args和關鍵字參數**kwargs print(f"[DEBUG]: enter {func.__name__}()") return func(*args, **kwargs) return wrapper #裝飾器函數返回的是裝飾完的函數 @printname def say_hello(): print("hello!") @printname def say_goodbye(): print("goodbye!") if __name__ == '__main__': say_hello() say_goodbye()
程序運行結果爲:blog
[DEBUG]: enter say_hello()
hello!
[DEBUG]: enter say_goodbye()
goodbye!
成功實現每次打印hello時打印出函數名稱say_hello()。
#間接裝飾 def printname(func): #裝飾器:實質是一個函數,參數是須要裝飾的函數名(非函數調用) def wrapper(*args, **kwargs): #可變參數*args和關鍵字參數**kwargs print(f"[DEBUG]: enter {func.__name__}()") return func(*args, **kwargs) return wrapper #裝飾器函數返回的是裝飾完的函數 def say_hello(): print("hello!") #return 0 測試line:23 def say_goodbye(): print("goodbye!") if __name__ == '__main__': decorator = printname(say_hello) ''' 不能使用decoratot = printname(say_hello()); 多是由於調用函數的名稱是用func.__name__,而非func().__name__ 用了func().name會報錯'NoneType'對象沒有'__name__'屬性。 由於say_hello()函數沒有return,故執行結果爲NoneType無。 ''' decorator() ''' 接上綠色註釋: >>> type(say_hello()) hello! <class 'NoneType'> >>> type(say_hello) <class 'function'> ''' #func,函數不帶括號時,調用的是這個函數自己。是一整個函數體,不須等函數執行完成。 #func(),函數帶括號時,調用的是函數的執行結果,須要等待函數執行完成的結果。
和@方法的區別主要在於如何使用裝飾器函數。咱們須要在調用時把執行函數傳入給裝飾函數,return 的結果返回給新函數;再運行新函數,就實行了這一效果。
1 def printname(func): 2 def wrapper(*args, **kwargs): 3 print(f"[DEBUG]: enter {func.__name__}()") 4 return func(*args, **kwargs) 5 return wrapper
實現了:print(裝飾)+ func(執行函數),即成功裝飾。
實質: 是一個函數
參數:是你要裝飾的函數名(並不是函數調用)
返回:是裝飾完的函數名(也非函數調用)
做用:爲已經存在的對象添加額外的功能
特色:不須要對對象作任何的代碼上的變更