Những gì mro () mv làm gì?


Câu trả lời:


211

Dõi theo...:

>>> 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 ta còn có sự kế thừa duy nhất, __mro__chỉ là bộ ba: lớp, cơ sở của nó, cơ sở của nó, v.v.object (tất nhiên chỉ hoạt động cho các lớp kiểu mới).

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

>>> 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 nào được sao chép và không có lớp nào xuất hiện sau tổ tiên của nó, lưu các lớp đầu tiên nhập vào cùng một mức độ thừa kế (như B và C trong ví dụ này) __mro__trái sang phải

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


9
chào, alex, có sự khác biệt nào giữa D .__ mro__ và D.mro ().
zjm1126

26
mrocó thể được tùy chỉnh bởi một siêu dữ liệu, đượ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 docs.python.org/l Library / .
Alex Martelli

23
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

1
Cũng giống như @ Alex Martelli nói và nội dung của python-history.blogspot.com/2010/06/... , các MRO thuộc tính nên add khi lớp mới được sử dụng, như chỉ khi Python 2.2 MRO và Python 2.3 MRO (C3) được sử dụng.
andy

82

mro()là viết tắt của Phương thức giải quyết lệnh. Nó trả về một danh sách các loại mà lớp có nguồn gốc, 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ó vấn đề gì. Nhưng trong python 2 các lớp đó cần phải kế thừa từ object.


10

Điều này có lẽ sẽ hiển thị thứ tự của độ 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 hồi 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à chiều sâu trước tiên, trong trường hợp này có nghĩa là D, B, A, C.

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


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

1
Ý bạn là gì khi "Python loại bỏ đề cập đầu tiên của lớp đó khỏi mro."?
Ruthvik Vaila

2
@RuthvikVaila: Tôi nghĩ rằng phần đó chỉ được nêu rõ. Trong bài viết trên blog này 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 được sao chép trong tìm kiếm này, tất cả ngoại trừ 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

1

Thứ tự giải quyết sẽ khác nhau trong thừa kế kim cương.

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

nhưng tại sao độ phân giải lại khác nhau?
Vadim

Trong kịch bản nhiều kế thừa, bất kỳ thuộc tính được chỉ định nào được tìm kiếm đầu tiên trong lớp hiện tại. Nếu không tìm thấy, tìm kiếm tiếp tục vào các lớp cha theo chiều sâu - trước, trái phải mà không tìm kiếm cùng một lớp hai lần.
Girish Gupta

xin lỗi nhưng tôi không hiểu tại sao trong trường hợp đầu tiên nó lại xảy ra class B3nhưng trong trường hợp thứ hai thì nó lại đến class Asauclass B1
Vadim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.