python中的super怎麼用?
面向物件有這個強大特點和作用, 著名的三大特點:封裝, 繼承, 多型
這篇部落格寫的是super()的簡單理解和使用
今天在讀restframework的原始碼的時候, 發現原始碼中使用了super, 依以此為入口, 重寫了django的as_view()
在程式碼執行的過程中既執行了自己的as_view()有執行了django的as_view()
super()能做什麼?
之前的理解就是, 使用super()可以在子類中呼叫父類的方法或屬性, 可能你會說, 子類本來就可以呼叫父類中所有非私有的屬性或方法,
而我現在說的是, 當子類中實現了某個方法, 父類中也有這個方法, 當你呼叫這個方法時, 既想執行子類的又想執行父類的, 在這種情況下
就可以使用super()
super()怎麼用的
class A(object): def __init__(self, name, age): self.name = name self.age = age print("class A") class B(A): def __init__(self, name, age): super().__init__(name, age) print("class B") class C(B):def __init__(self, name, age): # 方式一 super().__init__(name, age) # 相當於 super(C, self).__init__(name, age) # 預設是從當前類的父類開始往上找__init__() # 方式二 # 指定從當前類的某個父類中開始往上找 super(B, self).__init__(name, age) print("class C") c = C("sath", 37)
定義了三個類, 繼承關係為 C 繼承 B 繼承 A
定C類進行例項化的時候, 要先執行__init__()[__new__先不說],
C類中有__init__()方法, 所以就會執行C類中的__init__()
但是在C類自己的__init__()中卻使用了super(). 並且是 點.__init__()
這就表示要去執行父類的__init()方法
super()有兩中使用方法
方法一
super().__init__()
預設執行當前類的父類中的方法, 並且將當前類的例項物件self傳了進去
其實就相當於super(C, self).__init__()
父類中的__init__(self), 中的self就是super()傳進去的self,
方法二
super(B, self)>__init__()
其實和方法一一樣, 就是指定的父類不一樣了, 你可以指定執行那個父類的__init__()
前提是必須是當前這個類的父類
這樣執行的執行的話, 引數就會靈活很多
restframework中對super()的應用例項
先來看一下原始碼
@classmethod def as_view(cls, **initkwargs): if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet): def force_evaluation(): raise RuntimeError( 'Do not evaluate the `.queryset` attribute directly, ' 'as the result will be cached and reused between requests. ' 'Use `.all()` or call `.get_queryset()` instead.' ) cls.queryset._fetch_all = force_evaluation view = super(APIView, cls).as_view(**initkwargs) super().__init__() view.cls = cls view.initkwargs = initkwargs return csrf_exempt(view)
現在就來看這行程式碼 view = super(APIView, cls).as_view(**initkwargs)
寫了一個CBV, 檢視繼承了APIView
當請求進來之後, 進行路由匹配然後呼叫檢視函式, CBV會執行as_view()
我是的路由是這樣式的
url(r'^auth/', views.AuthView.as_view())
AuthView就是檢視類, 繼承了APIView, 當呼叫as_view()時, 先去自己的類中找as_view, 發現沒有, 然後去父類中找
上面的as_view()程式碼就是APIViwe類中的as_view(), APIView其實也繼承了View
發現as_view()是一個類方法, 怪不得在路由中使用類去呼叫呢, 這個樣就能得到檢視類的類空間了
因為在View中需要用檢視類, 然後對檢視類進行了例項化, 通過這個例項在加上反射獲取和使用者請求方式同名的函式並執行
上面就是super()在restframework中的應用