簡體   English   中英

在基類python / django上調用super

[英]calling super on base class python/django

在你將它標記為重復之前,讓我說明我理解超級工作的原理並且我已經閱讀了這三個鏈接:

“超級”在Python中做了什么?
使用__init __()方法理解Python super()
http://python-history.blogspot.nl/2010/06/method-resolution-order.html

對於baseclasses這就是super應該如何工作:

class X(object):
    def __init__(self):
        print "calling init from X"
        super(X, self).__init__()


class Y(object):
    def abc(self):
        print "calling abc from Y"
        super(Y, self).abc()

a = X()
# prints "calling init from X"  (works because object possibly has an __init__ method)

b = Y()
b.abc()
# prints "calling abc from Y" and then
# throws error "'super' object has no attribute 'abc'" (understandable because object doesn't have any method named abc)

問題:django核心實現中,有幾個地方使用從object繼承的super類來調用methods (在上面的例子中為Y )。 例如:有人可以解釋為什么這段代碼有效嗎?

from django.core.exceptions import PermissionDenied

class LoginRequiredMixin(object):

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated():
            raise PermissionDenied

        return super(LoginRequiredMixin, self).\
            dispatch(request, *args, **kwards)   # why does this work? 

參考:從這次演講中復制了這段代碼: https//youtu.be/rMn2wC0PuXw?t = 403

它的工作原理是因為LoginRequiredMixin旨在用於多繼承場景。 在這種情況下,MRO將解析為類層次結構的同一級別中的對象。 (與LoginRequiredMixin一起指定的其他類型)

您可以在下面看到訂單也很重要

Python 2.7.12 (default, Oct 11 2016, 05:20:59)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>> class Y(object):
...     def abc(self):
...         print "calling abc from Y"
...         super(Y, self).abc()
...
>>> class Z(object):
...     def abc(self):
...         print "calling abc from Z"
...
>>> class YZ(Y, Z):  # multiple inheritance
...     pass
...
>>> c = YZ()
>>> c.abc()
calling abc from Y
calling abc from Z
>>>
>>> class ZY(Z,Y): pass
...
>>> ZY().abc()
calling abc from Z

ZY基於MRO調用Z.abc ,因此Y.abc被忽略

您是否測試過該演示文稿中的所有代碼? 上面的代碼可能只有在有人做了一些不應該做的事情(並且在某些Python實現中被嚴格禁止)的情況下才能工作 - 修改Python內置函數。

您也可以這樣做 - 在執行或構建任何內容之前,請執行以下操作:

import __builtin__

class custom_object(object):
    def abc(self):
        print "calling abc from custom_object"

__builtin__.object = custom_object

然后嘗試構建XY類型,看看它是如何進行的。

PS只是為了強調某些內容,這僅用於教育目的 - 請勿使用此功能! 真的沒有必要訴諸於此,你只會為那些可能需要在未來解開你的代碼的開發人員謀生。

更新:

根據Josh J的上述建議, LoginRequiredMixin可能不打算用作獨立類,而是添加到多繼承鏈中。 在這種情況下,實現dispatch()方法和擴展object的基類可以粘貼到LoginRequiredMixin 考慮到Python如何處理MRO,來自LoginRequiredMixin super()實際上將引用'粘合'類'方法。

您可以使代碼行為相同,如:

class Y(object):
    def abc(self):
        print "calling abc from Y"
        super(Y, self).abc()

class Z(object):
    def abc(self):
        print "calling abc from Z"

class YZ(Y, Z):  # multiple inheritance
    pass

c = YZ()
c.abc()
# prints "calling abc from Y" and then
# prints "calling abc from Z"

它仍然是一個糟糕的框架設計的標志(只考慮我們花了多長時間才能根據相當簡單的代碼找到問題的底部),只是稍微不如亂搞內置。 所以,如果你有一天設計你的框架,請不要這樣做,不管怎樣

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM