一次错综离奇的super调用的None参数super() argument 1 must be type, not None
最近在python的代碼中,使用裝飾器的功能以后,遇到了一個有意思的錯誤,記錄下與大家分享一下,希望大家不會犯同樣的錯誤。
大致代碼如下:
fn_list = {}def decrator(fn):fn_list[fn.__name__] = fn@decrator def print_test(index):print(index)return 'success'@decrator class TestClass(object):def __init__(self):super(TestClass, self).__init__()print("finish init func")ouput_result = fn_list['print_test']('1234') print(ouput_result) test_instance = fn_list['TestClass']()運行的時候,在創建TestClass的對象的時候,報錯如下:
in __init__
super() argument 1 must be type, not None
檢查代碼的時候,先查看了fn_list[‘TestClass’]確實指向了對應的類,不是None。
在__init__函數中,輸出self,發現是對應類的對象,然后輸出TestClass,發現是None。
但是調用同樣用裝飾器裝飾的print_test沒有發生問題。
其實問題就出在裝飾器函數上,裝飾器的作用其實就是在對象(例如函數,類)定義的時候 改變這個對象后續調用過程中的行為,又不改變這個對象內部代碼。
以裝飾某一個函數為例子,比如裝飾器是decrator函數,裝飾在print_test函數,那么在函數print_test定義的時候(此時函數print_test不被調用),首先調用了一次print_test = decorator(print_test),對于print_test的函數進行定義。那么,此時指向print_test對象的指針,已經被替換成了指向decorator(print_test)的指針。這里需要注意的是,此時print_test函數已經被覆蓋成了新的函數decorator(print_test),即調用decorator函數,并將print_test作為參數傳入,得到的返回值,即print_test = decorator(print_test)。
詳細的了解了裝飾器的工作機制,就不難理解上述問題的出現了。
首先,為什么調用print_test會有正確的結果,這個是因為在裝飾器中,保存了print_test的調用入口,并且是通過這個入口調用的(ouput_result = fn_list['print_test']('1234')
)。但是,如果直接調用print_test('1234'),會出錯。
其次,創建對象為什么會報錯。這個是因為,創建對象調用,從保留的正確入口進行了調用(fn_list['TestClass']()),但是,在類初始化的__init__函數中,調用super的時候,是用的函數名稱TestClass進行直接調用的,這個時候,其實TestClass已經在定義的時候,因為調用TestClass = decorator(TestClass) 而變成了None(decorator沒有顯式指定返回值,所以為默認返回值None),這樣就產生了最終的這個錯綜離奇的報錯。
太長不看系列:
裝飾器原理,對于用裝飾器修飾的函數定義:
@decorator
def func():
pass
在定義時,先調用了func = decorator(func),對于func進行了定義的修改。
由于decorator在我的代碼中沒有顯式定義返回值,則使用的默認返回值None。
于是所有被裝飾的函數和類,都被設置為None的變量。
修改辦法
def decrator(fn):fn_list[fn.__name__] = fnreturn fn總結
以上是生活随笔為你收集整理的一次错综离奇的super调用的None参数super() argument 1 must be type, not None的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle VM VirtualBox
- 下一篇: ME811 刷机