ماذا يفعل "MRO ()"؟
-
18-09-2019 - |
سؤال
في django.utils.functional.py
:
for t in type(res).mro(): # <----- this
if t in self.__dispatch:
return self.__dispatch[t][funcname](res, *args, **kw)
أنا لا أفهم mro()
. وبعد ماذا يفعل وماذا يعني "MRO"؟
المحلول
اتبع جنبا إلى جنب ...:
>>> class A(object): pass
...
>>> A.__mro__
(<class '__main__.A'>, <type 'object'>)
>>> class B(A): pass
...
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
>>> class C(A): pass
...
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
>>>
طالما لدينا ميراث واحد، __mro__
هو مجرد tuple من: الفصل، وقاعدةها، قاعدة قاعدة، وما إلى ذلك object
(يعمل فقط لفئات النمط الجديد بالطبع).
الان مع مضاعف ميراث...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... أنت أيضا الحصول على ضمان ذلك، في __mro__
, ، لا يتم تكرار أي فئة، ولا يأتي أي فئة بعد أسلافها، وحفظ تلك الفصول الدراسية التي تدخل أولا بنفس المستوى من الميراث المتعدد (مثل B و C في هذا المثال) موجودة في __mro__
من اليسار إلى اليمين.
كل سمة تحصل على مثيل الفصل، وليس فقط الأساليب، يتم النظر في الناحية الفنية على طول __mro__
, ، لذلك، إذا كان أكثر من فئة واحدة بين الأجداد يحدد هذا الاسم، فإن هذا يخبرك حيث سيتم العثور على السمة - في الدرجة الأولى في __mro__
هذا يحدد هذا الاسم.
نصائح أخرى
mro()
تقف لطلب قرار الأسلوب. ترجع قائمة الأنواع التي يتم فيها مشتق الفصل، بالترتيب الذي يتم البحث فيه عن طرق.
MRO () أو __mro__ يعمل فقط على دروس نمط جديد. في بيثون 3، يعملون دون أي مشاكل. ولكن في بيثون 2 هذه الفصول تحتاج إلى الوراثة من الأشياء.
هذا ربما يظهر ترتيب القرار.
class A(object):
def dothis(self):
print('I am from A class')
class B(A):
pass
class C(object):
def dothis(self):
print('I am from C class')
class D(B, C):
pass
d_instance= D()
d_instance.dothis()
print(D.mro())
والاستجابة سيكون
I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
القاعدة هي العمق - أولا، والتي في هذه القضية تعني D، B، A، C.
يستخدم بيثون عادة العمق أولا من أجل البحث عند البحث عن الفصول الدراسية، ولكن عندما ترث فئتين من نفس الفصل، يزيل Python أول ذكر لتلك الفئة من MRO.
سيكون ترتيب القرار مختلفا في ميراث الماس.
class A(object):
def dothis(self):
print('I am from A class')
class B1(A):
def dothis(self):
print('I am from B1 class')
# pass
class B2(object):
def dothis(self):
print('I am from B2 class')
# pass
class B3(A):
def dothis(self):
print('I am from B3 class')
# Diamond inheritance
class D1(B1, B3):
pass
class D2(B1, B2):
pass
d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)
d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)