1. 程式人生 > >python中的super怎麼用?

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中的應用