Trăn thừa kế kim cương

Khi thiết lập hướng đối tượng với Python, ta thường bắt gặp các câu lệnh như

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
0 hoặc
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
1 nhất là khi đọc tài liệu của các thư viện có các lớp kế thừa nhiều lần. Bài viết hôm nay của mình sẽ hướng đến giới thiệu hàm
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 và các trường hợp sử dụng nó

1. Kế thừa trong Python

Để hiểu rõ hơn về vai trò của

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2. Mình sẽ bắt đầu với trường hợp không sử dụng
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 trong kế thừa trước. Cho lớp cha
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5 và được kế thừa bởi lớp con
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
6, khi đó lớp
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7 có thể gọi các phương thức hoặc thuộc tính từ lớp cha

________số 8

Tuy nhiên, sẽ xảy ra trường hợp

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5 có phương thức trùng tên với nhau là
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
10 và ta cần gọi phương thức
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
10 của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5 bên trong phương thức
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
13 của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7. Trường hợp này vẫn có thể được giải quyết mà không cần sử dụng đến
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 bằng cách gọi trực tiếp
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
16 bên trong
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
17

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
9

Nhiều bạn đã biết về phương thức ràng buộc, phương thức không ràng buộc có thể sẽ thắc mắc tại sao lại sử dụng tham số

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
18 cho phương thức
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
10 dù hàm này không sử dụng thuộc tính hay phương thức của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
18. Vì mình muốn tập trung vào giới thiệu phương pháp kế thừa nên đã viết đơn giản hơn vì có thêm decorator và thay đổi cách gọi hàm. Bạn nào có nhu cầu tìm hiểu thêm về phương pháp có ràng buộc, phương pháp không có ràng buộc có thể tham khảo tại đây

Chúng ta cũng có thể giải quyết trường hợp này bằng cách sử dụng

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 thay vì gọi trực tiếp

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class

Hàm

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 lúc này sẽ trả về một đối tượng thuộc lớp kế thừa từ
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7 lúc này là
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5 và gọi là
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
85. Khác với cách gọi trực tiếp,
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 không cần viết lại tên lớp
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5 khi gọi hàm, công việc này sẽ giúp tránh các lỗi mô tả chính xác hoặc bạn có nhu cầu đổi tên lớp cha hoặc kế thừa từ lớp khác.
Nhưng đấy vẫn chưa phải là tất cả điểm mạnh của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2.
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 được sử dụng linh hoạt trong các trường hợp đa kế thừa đặc biệt là mà mình sẽ giới thiệu sau đây. Trước hết chúng ta cần phải hiểu rõ một vài khái niệm và các tham số của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2

2. Thứ tự giải quyết phương pháp [MRO]

MRO có thể hiểu đơn giản là trình tự kế thừa của lớp. MRO của một lớp có thể được truy xuất bằng phương thức
MRO sẽ được tạo để đảm bảo các lớp chỉ được liệt kê một lần và các lớp con phải được gọi trước lớp cha. Nếu bạn muốn tìm hiểu thêm về thuật toán tạo MRO của Python thì tham khảo tại đây

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
1

Khi sử dụng một phương thức với các đối tượng thuộc Lớp con, chương trình sẽ tìm kiếm phương thức dựa trên thứ tự MRO như trên, tức là bắt đầu từ Lớp con, nếu không có thì tìm kiếm sẽ đến Lớp cha và sau cùng là [lớp cơ sở

3. Tham số của hàm
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2

Hàm

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
63 sẽ nhận vào hai tham số
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
64 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
65

  • class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    64 sẽ nhận giá trị kiểu lớp để khi tìm kiếm phương thức hoặc thuộc tính, chương trình sẽ tìm các lớp cha sau
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    64 trong MRO của lớp. dựa vào
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    64 ta có thể quyết định phương thức cần gọi được cài đặt trong Lớp cha hoặc Lớp ông nội
  • class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    65 sẽ nhận vào một đối tượng để ràng buộc [ràng buộc] với phương thức hoặc thuộc tính được gọi bởi
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    2

Để dễ hình dung,

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
41 có thể hiểu là
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
42 với phương thức
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
43 được cài đặt trong lớp cha của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
64

Các ví dụ trên, hàm

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 được gọi trong lớp
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7 sẽ có giá trị tham số mặc định là
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
47

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
8

Ngoài

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
64 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
65 còn có một số ràng buộc để chương trình chạy không bị lỗi mà bạn có thể tham khảo tại của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2

Lưu ý. If in ________ 551 of layer ________ 552 call next ________ 553. Hàm sẽ tìm thấy

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
51 của các lớp phía sau lớp
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
52 trong MRO. Ở đây MRO sẽ là
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
56, vì
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
65 không được cài đặt
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
51 nên sẽ trả về lỗi
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
59

4. Giải quyết Vấn đề kim cương bằng super[]


Sự cố kim cương xuất hiện khi ta thực hiện đa kế thừa trên hai lớp cha cùng kế thừa từ một lớp nội.
Xét trường hợp ta có các lớp sau.

  • Lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    52
  • Lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    51 và lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    52 cùng kế thừa từ lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    53
  • Lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    54 đa kế thừa từ hai lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    55 và
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    56

Khi đó chúng ta sẽ gặp các vấn đề phát sinh sau

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
55 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
56 có trùng tên nhau

Nếu bạn gọi phương thức bằng

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2, phương thức của lớp có thứ tự nhỏ hơn trong MRO sẽ được gọi trước. Trong trường hợp này, lớp cha thứ tự trong MRO sẽ là thứ tự liệt kê lớp cha trong lúc khai báo Lớp
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
6

Nếu muốn gọi

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
51 của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
56 ta có thể làm như sau

  • Change thứ tự báo cáo
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    83
  • Call direct
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    84

Phương thức của lớp

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
52 được gọi lại hai lần

Vấn đề này gặp phải khi chúng ta muốn gọi phương thức khởi tạo của

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
55 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
56 trực tiếp bên trong
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
7, nhưng phương thức khởi tạo của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
55 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
56 lại gọi lại phương thức khởi tạo của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
53. Khi đó sẽ xảy ra việc phương thức khởi tạo của
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
53 bị gọi 2 lần

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
4

Cách giải quyết. use function

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 instead of call direct. Như đã lưu ý ở mục 3. hàm
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 sẽ tìm các phương thức khởi tạo dựa trên MRO và lớp hiện tại. Vì các lớp chỉ xuất hiện trong MRO duy nhất một lần nên khi gọi
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
0 sẽ tránh được cuộc gọi nhiều lần, giảm thiểu thời gian chạy và tránh bị ghi không cần thiết

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5

Tuy nhiên, điều này lại dẫn đến vấn đề sau

Phương thức khởi tạo của

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
55 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
56 cần có các tham số khác nhau
Giả sử ta cần lưu số tuổi của mỗi lớp thông qua các biến
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
908,
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
909,
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
910 và
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
911< .
Xét đoạn code sau đây:

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
5

Mỗi lớp đều cần tham số khác nhau khi khởi động nên theo thứ tự MRO đã biết trước, chúng ta có thể viết mã như trên. Tuy code chạy đúng như ý muốn nhưng mình tin ảo ai muốn code as on vì các lý do sau

  • Sai bản chất. ngoại trừ khi
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    55 và
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    56 chỉ được khởi động đúng một lần và chỉ sử dụng để tạo lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    7, với mã trên khi tạo đối tượng thuộc lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    55 hoặc
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    56 sẽ bị lỗi dư tham số
  • Reshard hard. Vì tham số truyền vào
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    917 dựa trên MRO nên sẽ phụ thuộc thứ tự khai báo của lớp, chỉ cần thay đổi thứ tự lại là có thể làm cho mã chạy bị lỗi
  • Khó tái sử dụng. Giả sử như chúng ta có thêm lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    918 và muốn tạo lớp đa kế thừa từ
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    55 và
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    918. Khi đó ta phải viết lại
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    917 của
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    55 để đa kế thừa, điều này có thể ảnh hưởng đến lớp
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    7 hiện tại

Cách giải quyết. used

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
924 in
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
917. Khi đó chúng ta cần phải thiết kế lại tất cả các phương thức
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
917 của tất cả các lớp

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
8

Mã vẫn trả về kết quả như ý nhưng gọn hơn và dễ bảo trì, mở rộng hơn

Chúng ta vẫn có thể giải quyết trường hợp này bằng cách gọi phương thức khởi tạo trực tiếp nếu bạn chắc chắn không bị ghi đè lên lớp

class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
52 hoặc ghi đè không gây ảnh hưởng gì [nhưng mình vẫn hoan nghênh việc sử dụng
class Children[Parent]:
    def self_intro[self]:
        print["This is children class"]

    def family_intro[self]:
        self.self_intro[] # Same as Children.self_intro[self]
        super[].self_intro[]

c = Children[]
c.family_intro[]
# >>> This is children class
# >>> This is parent class
2 hơn vì . ]

5. Kết bài

Qua bài này mình đã trình bày với các bạn

  • Call the method from layer cha by
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    2 or direct next
  • MRO MRO và ý nghĩa tham số của
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    2
  • Vấn đề kim cương và cách giải quyết bằng
    class Children[Parent]:
        def self_intro[self]:
            print["This is children class"]
    
        def family_intro[self]:
            self.self_intro[] # Same as Children.self_intro[self]
            super[].self_intro[]
    
    c = Children[]
    c.family_intro[]
    # >>> This is children class
    # >>> This is parent class
    
    2

Nếu bài viết có chỗ nào không rõ hoặc sai thì xin hãy cho mình biết. Cảm ơn các bạn đã dành thời gian đọc bài viết này

Chủ Đề