[英]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
然后嘗試構建X
和Y
類型,看看它是如何進行的。
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.