2010-01-06 13 views
91

Trong django.utils.functional.py:"mro()" làm gì?

for t in type(res).mro(): # <----- this 
    if t in self.__dispatch: 
     return self.__dispatch[t][funcname](res, *args, **kw) 

Tôi không hiểu mro(). Nó làm gì và "mro" nghĩa là gì?

+2

http://www.python.org/download/releases/2.3/mro – GodMan

+1

Ooph, những gì đọc được lâu. – paulmelnikow

Trả lời

164

theo cùng ...:

>>> 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'>) 
>>> 

Chừng nào chúng tôi có thừa kế duy nhất, __mro__ chỉ là tuple của: lớp, cơ sở của nó, căn cứ của cơ sở, và vân vân lên đến object (chỉ hoạt động cho các lớp học theo phong cách mới của khóa học).

Bây giờ, với nhiều thừa kế ...:

>>> class D(B, C): pass 
... 
>>> D.__mro__ 
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) 

... bạn cũng có được sự đảm bảo rằng, trong __mro__, không có lớp được nhân đôi, và không có lớp đưa ra sau khi tổ tiên của mình, tiết kiệm mà các lớp mà lần đầu tiên nhập vào cùng cấp độ đa thừa kế (như B và C trong ví dụ này) nằm trong số __mro__ từ trái sang phải.

Mỗi thuộc tính bạn nhận được trên cá thể của lớp, không chỉ là phương pháp, được khái niệm tra dọc theo __mro__, vì vậy, nếu có nhiều hơn một lớp trong tổ tiên xác định tên đó, điều này sẽ cho bạn biết thuộc tính sẽ được tìm thấy ở đâu - trong lớp đầu tiên trong số __mro__ xác định tên đó.

+7

hi, alex, có sự khác biệt nào giữa D .__ mro__ và D.mro() hay không. – zjm1126

+19

'mro' có thể được tùy chỉnh bằng metaclass, được gọi một lần khi khởi tạo lớp và kết quả được lưu trữ trong' __mro__' - xem http://docs.python.org/library/stdtypes.html?highlight=mro# lớp .__ mro__. –

+13

Tại sao nó được gọi là ** thứ tự độ phân giải phương thức ** thay vì ** thứ tự độ phân giải thuộc tính **? – Bentley4

69

mro() là viết tắt của Phương thức phân giải phương pháp. Nó trả về một danh sách các kiểu lớp được bắt nguồn từ, theo thứ tự chúng được tìm kiếm cho các phương thức.

mro() hoặc __mro__ chỉ hoạt động trên các lớp kiểu mới. Trong python 3, chúng hoạt động mà không có bất kỳ vấn đề gì. Nhưng trong python 2 những lớp đó cần phải kế thừa từ các đối tượng.

7

Điều này có thể hiển thị thứ tự độ phân giải.

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()) 

và phản ứng sẽ là

I am from A class 
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>] 

Quy tắc là nợ đầu tiên mà trong trường hợp này có nghĩa là D, B, A, C

Python thường sử dụng một trật tự sâu-đầu tiên khi tìm kiếm kế thừa các lớp Nhưng khi hai lớp kế thừa từ cùng một lớp, Python loại bỏ đề cập đầu tiên của lớp đó từ mro.

+1

Vì vậy, bạn có thể thấy thứ tự là D, B, A, C – Stryker

+1

Ý của bạn là gì? "Python loại bỏ đề cập đầu tiên của lớp đó từ mro."? –

+1

@RuthvikVaila: Tôi nghĩ rằng phần đó không được nêu rõ. Trong [bài đăng blog] này (http://python-history.blogspot.com/2010/06/method-resolution-order.html) về lịch sử của Python, Guido van Rossum nhận xét (về sơ đồ MRO được giới thiệu trong Python 2.2) "Nếu bất kỳ lớp nào bị trùng lặp trong tìm kiếm này, tất cả nhưng ** lần xuất hiện ** cuối cùng sẽ bị xóa khỏi danh sách MRO" (nhấn mạnh của tôi). Điều này ngụ ý rằng nó có thể loại bỏ nhiều hơn chỉ là "đề cập" đầu tiên của lớp. – martineau