Hướng dẫn python inherit only some attributes - python chỉ kế thừa một số thuộc tính

Tôi đang tạo một lớp (Class0) trong Python hiện đang dựa trên một lớp (Class1); Tuy nhiên, tôi cũng muốn được thừa hưởng từ một lớp khác (Class2). Điều về Class2 là tôi không muốn tất cả các phương thức và thuộc tính của nó, tôi chỉ cần một phương thức duy nhất. Có thể Class0 chỉ kế thừa một phương thức duy nhất tạo thành một lớp2?

Hỏi ngày 13 tháng 4 năm 2011 lúc 9:31Apr 13, 2011 at 9:31

Hướng dẫn python inherit only some attributes - python chỉ kế thừa một số thuộc tính

hình chữ nhậtrectangletangle

48.4K91 Huy hiệu vàng199 Huy hiệu bạc273 Huy hiệu Đồng91 gold badges199 silver badges273 bronze badges

1

Phương pháp "mixin" để có một lớp khác chỉ cần thực hiện phương thức bạn muốn là điều chính xác để làm trong trường hợp này. Nhưng để hoàn thiện, vì nó trả lời chính xác những gì bạn đang hỏi, tôi nói thêm rằng có, có thể có một hành vi giống như "thừa kế một phần" mà bạn muốn (nhưng lưu ý rằng một khái niệm như vậy không tồn tại chính thức).

Tất cả mọi người phải làm là thêm thành viên trên lớp mới đề cập đến phương thức hoặc thuộc tính bạn muốn lặp lại ở đó:

class Class2(object):
   def method(self):
      print ("I am method at %s" % self.__class__)

class Class1(object):
   pass

class Class0(Class1):
   method = Class2.__dict__["method"]

ob = Class0()
ob.method()

Lưu ý rằng việc truy xuất phương thức từ lớp

method = Class2.__dict__["method"]
7 là cần thiết trong Python 2.x (lên đến 2.7) - do các biến đổi thời gian chạy được thực hiện để chuyển đổi hàm theo phương thức. Trong Python 3.0 trở lên, chỉ cần thay đổi dòng

method = Class2.__dict__["method"]

đến

method = Class2.method

Đã trả lời ngày 13 tháng 4 năm 2011 lúc 11:47Apr 13, 2011 at 11:47

JSbuenojsbuenojsbueno

90,9k10 Huy hiệu vàng140 Huy hiệu bạc194 Huy hiệu đồng10 gold badges140 silver badges194 bronze badges

Một đường dẫn là sử dụng phương pháp 'mixin':

class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass

Một cách khác là bố cục:

class C1(object):
    def method(self):
        pass

class C2(object):
    def __init__(self):
        self.c1 = C1()

    def method(self):
        return self.c1.method()

Đã trả lời ngày 13 tháng 4 năm 2011 lúc 9:41Apr 13, 2011 at 9:41

Zindelzindelzindel

1.79710 Huy hiệu bạc13 Huy hiệu đồng10 silver badges13 bronze badges

2

Tại sao bạn không sử dụng sáng tác thay thế? Yêu cầu lớp của bạn giữ một tham chiếu đến đối tượng mong muốn và ủy thác cho nó.

Đã trả lời ngày 13 tháng 4 năm 2011 lúc 9:33Apr 13, 2011 at 9:33

GEOGEOGeo

91.3K115 Huy hiệu vàng338 Huy hiệu bạc514 Huy hiệu đồng115 gold badges338 silver badges514 bronze badges

2

Tạo một lớp cơ sở khác thực hiện phương pháp này và tạo ra Class2 và Class1 cả hai kế thừa lớp này

Đã trả lời ngày 13 tháng 4 năm 2011 lúc 9:33Apr 13, 2011 at 9:33

GEOGEOAndrey Sboev

91.3K115 Huy hiệu vàng338 Huy hiệu bạc514 Huy hiệu đồng1 gold badge19 silver badges35 bronze badges

Giả sử có một loại A với hàng tá phương pháp. Đối với các mục đích của tôi, tôi chỉ cần 2 hoặc 3 phương pháp "thú vị" của lớp A trong lớp mới của tôi B. Hơn nữa, tôi muốn mở rộng lớp B với một số phương pháp của riêng tôi. Kế thừa thường được thực hiện với lớp B (a): Phương thức def1 (): ... Phương thức def2 (): ... Nhưng sau đó tôi có một loạt các phương pháp thừa của A In B. Có cách nào tôi có thể chọn một số Các phương thức từ tương tự như trong thông báo nhập khẩu, nơi tôi có thể giới hạn các phương thức được truy cập, do đó để nói một kế thừa một phần. Tôi muốn có một cái gì đó là lớp B (từ một phương thức lấy, methody): def newmethod1 (): ... def newmethod2 (): ... def newmethod3 (): ...

Trong bài học này, chúng ta sẽ nói về cách xây dựng các lớp dựa trên các lớp hiện có. Có hai cách tiếp cận để làm điều này, kế thừa và sáng tác. Mỗi người có điểm mạnh và điểm yếu của nó. Chúng tôi sẽ nhìn vào từng người ở đây.inheritance and composition. Each has its strengths and weaknesses. We’ll look at each here.

Di sản¶

Trong lập trình hướng đối tượng (OOP), kế thừa là một cách để tái sử dụng mã của các đối tượng hiện có. Nó rất tốt khi bạn muốn thiết lập một kiểu con từ một đối tượng hiện có. Các đối tượng được xác định bởi các lớp, các lớp có thể kế thừa các thuộc tính và hành vi từ các lớp có sẵn. Các lớp kết quả được gọi là các lớp dẫn xuất hoặc các lớp con.

Một lớp con được thừa hưởng tất cả các thuộc tính (phương thức, v.v.) của lớp cha. Chúng ta có thể tạo các thuộc tính hoặc phương thức mới để thêm vào hành vi của cha mẹ, chúng ta có thể thay đổi (ghi đè lên) một số hoặc tất cả các thuộc tính hoặc phương thức để thay đổi hành vi. Chúng tôi cũng có thể mở rộng hành vi của cha mẹ bằng cách sử dụng các phương thức ban đầu và thêm một chút nữa.

Chúng tôi chỉ ra rằng một lớp mới nên kế thừa từ một lớp hiện có bằng cách đặt tên của lớp hiện có trong danh sách các lớp cơ sở. Lớp (ES) được đặt tên trong danh sách các lớp cơ sở phải nằm trong không gian tên hiện tại khi câu lệnh của lớp được đánh giá. Để tương thích trên Python 2 và 3, bất kỳ lớp mới nào chúng tôi tạo ra sẽ luôn được thừa kế từ ít nhất

method = Class2.__dict__["method"]
8. Lớp cơ bản này nằm ở đầu mô hình dữ liệu Python và nằm trong không gian tên
method = Class2.__dict__["method"]
9.

Đây là mô hình giả giả cho lớp con đơn giản nhất trong Python:

class Subclass(Superclass):
    pass

method = Class2.method
0 hiện có chính xác hành vi giống như
method = Class2.method
1

Ghi chú

Khi chúng ta đặt

method = Class2.__dict__["method"]
8 trong danh sách lớp cơ sở, điều đó có nghĩa là chúng ta đang kế thừa từ đối tượng - nhận chức năng cốt lõi của tất cả các đối tượng.

Ghi đè các thuộc tính

Một trong những mục đích cốt lõi của một lớp con là thay đổi hành vi của lớp cha theo một cách hữu ích nào đó. Chúng tôi gọi điều này ghi đè hành vi kế thừa. Ghi đè các thuộc tính của lớp cha trong Python cũng đơn giản như tạo một thuộc tính mới có cùng tên:

class Circle(object):
    color = "red"

class NewCircle(Circle):
    color = "blue"

nc = NewCircle
print(nc.color)
blue

Bất kỳ trường hợp nào của lớp mới sẽ có màu

method = Class2.method
3. Các trường hợp của lớp ban đầu sẽ có màu
method = Class2.method
4.

Phương pháp ghi đè

Các phương thức ghi đè hoạt động chính xác theo cùng một cách (hãy nhớ, một phương thức là một thuộc tính trong Python).

class Circle(object):
...
    def grow(self, factor=2):
        """grows the circle's diameter by factor"""
        self.diameter = self.diameter * factor
...

class NewCircle(Circle):
...
    def grow(self, factor=2):
        """grows the area by factor..."""
        self.diameter = self.diameter * math.sqrt(2)

Các phiên bản của lớp Circle mới sẽ có hành vi mới cho phương thức

method = Class2.method
5. Các trường hợp của lớp hiện tại sẽ tiếp tục có hành vi cũ.

Khi ghi đè hành vi cho một lớp con, hãy nhớ rằng trong chương trình OO tốt, một lớp con phải tương tự như cha mẹ của nó. Nếu bạn có một hệ thống sử dụng lớp cha, bạn sẽ có thể sử dụng lớp con ở tất cả các nơi tương tự và theo cùng một cách. Điều này được gọi là nguyên tắc thay thế của Liskov. Các tác giả của

method = Class2.method
6 đặt nó theo cách này:

whenever you override a method, the interface of the new method should be
the same as the old.  It should take the same parameters, return the same
type, and obey the same preconditions and postconditions.

If you obey this rule, you will find that any function designed to work
with an instance of a superclass, like a Deck, will also work with
instances of subclasses like a Hand or PokerHand.  If you violate this
rule, your code will collapse like (sorry) a house of cards.

-- [ThinkPython 18.10]

Phương pháp mở rộng

Muốn hoặc cần ghi đè

method = Class2.method
7 là rất phổ biến. Rốt cuộc, chúng tôi đang cố gắng sửa đổi cách thức hoạt động của lớp cha. Tuy nhiên, chúng tôi cũng thường muốn làm một số hoặc tất cả những điều mà lớp cha làm với
method = Class2.method
7. Chúng tôi thực sự muốn mở rộng chức năng của lớp cha
method = Class2.method
7. Hãy nghĩ rằng làm mọi thứ mà cha mẹ tôi làm, cộng với những thứ khác.

class Circle(object):
    color = "red"
    def __init__(self, diameter):
        self.diameter = diameter
...
class CircleR(Circle):
    def __init__(self, radius):
        diameter = radius*2
        Circle.__init__(self, diameter)

Bạn có thể làm điều tương tự với bất kỳ phương pháp nào của lớp cha. Có bất cứ điều gì đặc biệt về phương pháp

method = Class2.method
7 (ngoại trừ nó được gọi là tự động).

method = Class2.__dict__["method"]
0

Đơn hàng giải quyết thuộc tính

Chúng tôi đã thảo luận về cách Python tìm kiếm các thuộc tính của một thể hiện lớp. Nó bắt đầu trong không gian tên của trường hợp, và sau đó nhìn vào không gian tên của lớp. Điều gì xảy ra khi lớp của bạn là một lớp con? Nếu tên không được tìm thấy trong không gian tên của ví dụ của chúng tôi hoặc trong lớp, thì tìm kiếm tiếp tục trong lớp cha, v.v.

  • Nó có phải là một thuộc tính thể hiện không?
  • Nó có phải là một thuộc tính lớp?
  • Nó có phải là một thuộc tính siêu lớp?
  • Nó có phải là một thuộc tính siêu cấp?
  • ...

Quá trình tìm kiếm các thuộc tính của một lớp trong hệ thống phân cấp kế thừa có vẻ tương đối đơn giản. Nhưng Python cũng hỗ trợ nhiều kế thừa (hai hoặc nhiều tên trong danh sách lớp cơ sở). Điều gì xảy ra sau đó?

Trong Python 2.3, một thuật toán mới đã được thêm vào Python để làm rõ câu hỏi này. Tài liệu rõ ràng nhất về nó có thể được tìm thấy trong các ghi chú phát hành cho 2.3 và trong một bài đăng trên blog về lịch sử của blog Python.

Đối với mục đích của chúng tôi, đủ để nói rằng nếu bạn có bất kỳ câu hỏi nào, bạn có thể sử dụng phương pháp

class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass
1 của bất kỳ lớp kiểu mới nào để có được danh sách các lớp cha được đặt hàng của nó:

method = Class2.__dict__["method"]
1

Từ viết tắt

class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass
2 là viết tắt của
class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass
3. Rõ ràng, mặc dù, nó áp dụng cho tất cả các thuộc tính của một lớp, không chỉ cho các phương thức.

Một lưu ý cuối cùng, liên quan đến việc sử dụng

method = Class2.__dict__["method"]
8 trong danh sách lớp cơ sở cho một lớp. Trong Python 2, đây là cách chúng tôi phân biệt các lớp học theo phong cách mới với các lớp học kiểu cũ. Các lớp học kiểu cũ có một cách khác để xử lý độ phân giải thuộc tính. Nó công bằng kém khi được sử dụng với nhiều kế thừa. Các lớp học theo phong cách mới đã làm tốt hơn với điều này, đặc biệt là sau Python 2.3 nhưng các lớp học kiểu cũ vẫn còn xung quanh.

Trong Python 3, không có thứ gọi là các lớp kiểu cũ. Tất cả các lớp kế thừa từ

method = Class2.__dict__["method"]
8 cho dù được chỉ định hay không. Chúng tôi cung cấp lớp cơ sở
method = Class2.__dict__["method"]
8 để duy trì khả năng tương thích giữa Python 2 và Python 3.

Khi nào đến lớp con

Hãy nhớ rằng chúng tôi đã tuyên bố trước đây rằng việc thừa kế nên được sử dụng chủ yếu để thúc đẩy việc sử dụng lại mã. Nó thực sự có nghĩa là được sử dụng khi thứ bạn muốn xây dựng là một biến thể trên lớp cha.

Nếu bạn muốn có thể sử dụng lớp mới của mình ở tất cả các địa điểm và trong tất cả các cách mà bạn có thể sử dụng cha mẹ, thì nó nên thừa hưởng từ cha mẹ. Nhưng đây không phải là lựa chọn duy nhất có thể.

Thành phần¶

Hãy để tưởng tượng rằng chúng ta có một lớp cần tích lũy một số lượng đối tượng tùy ý. Một danh sách có thể làm điều đó, vì vậy chúng ta nên danh sách phân lớp, phải không?

Vấn đề là, ngoài việc có thể tích lũy các đối tượng, liệt kê hỗ trợ một số hoạt động khác. Chúng ta có thể lặp lại các đối tượng chúng chứa. Chúng ta có thể sắp xếp và đảo ngược chúng.

Lớp học mới của chúng ta có cần phải làm tất cả những điều đó không? Nếu câu trả lời là không, thì lớp mới của chúng tôi có thể được phục vụ tốt hơn bằng cách chứa một danh sách, thay vì kế thừa từ nó.

Thành phần là một phương pháp lập trình định hướng đối tượng khác. Chúng tôi sử dụng nó khi chúng tôi muốn sử dụng một số khía cạnh của một lớp khác mà không hứa hẹn tất cả các tính năng của lớp khác.

Hãy suy nghĩ về ví dụ của chúng tôi. Có lẽ các đối tượng tích lũy là tất cả những gì chúng tôi muốn lớp mới này làm. Không có chức năng khác từ một danh sách là bắt buộc. Chúng tôi có thể xây dựng lớp của mình để chứa một danh sách:

method = Class2.__dict__["method"]
2

Bây giờ, chúng ta có thể xây dựng một thể hiện của lớp

class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass
7 của chúng ta và bắt đầu tích lũy công cụ:

method = Class2.__dict__["method"]
3

Và thường xuyên, chúng ta thậm chí có thể yêu cầu xem những gì trong ngăn kéo rác (mặc dù giống như bất kỳ ngăn kéo rác nào tốt mà bạn có thể thực sự lấy ra bất cứ thứ gì):

method = Class2.__dict__["method"]
4

Công văn dựa trên loại

Một từ cuối cùng cho bài học này về các lớp học. Thỉnh thoảng chúng tôi sẽ thấy mã trông như thế này:

method = Class2.__dict__["method"]
5

Nói chung, nó thường tốt hơn khi sử dụng đánh máy vịt (đa hình). Rốt cuộc, nếu

class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass
8 có các phương thức hoặc thuộc tính phù hợp, thì tại sao chúng ta lại quan tâm nếu đó là một ví dụ của
class Mixin(object):
    def method(self):
        pass

class C1(Mixin, ...parents...):
    pass

class C2(Mixin, ...parents...):
    pass
9? Nhưng khi nó được gọi, bạn có thể sử dụng
class C1(object):
    def method(self):
        pass

class C2(object):
    def __init__(self):
        self.c1 = C1()

    def method(self):
        return self.c1.method()
0 hoặc anh em họ
class C1(object):
    def method(self):
        pass

class C2(object):
    def __init__(self):
        self.c1 = C1()

    def method(self):
        return self.c1.method()
1 của nó:

method = Class2.__dict__["method"]
6

Gói (lại¶

Trong bài giảng này, chúng tôi đã tìm hiểu về phân lớp và sáng tác, hai cách tiếp cận để lập trình OO. Chúng tôi đã học cách làm một lớp con trong Python. Chúng tôi đã tìm hiểu về thứ tự phân giải phương thức và cách các thuộc tính được tra cứu khi kế thừa đang diễn ra. Chúng tôi cũng đã tìm hiểu về sự khác biệt giữa các lớp cũ và kiểu mới và cách duy trì khả năng tương thích trong Python 3. Cuối cùng, chúng tôi đã học cách sử dụng thành phần để có quyền truy cập vào một số quyền hạn của một lớp khác mà không cần phải thừa hưởng tất cả.

Khi bạn làm việc trên các bài tập cấu trúc dữ liệu của mình, hãy xem xét làm thế nào các công cụ mới này có thể giúp bạn.

Làm thế nào để bạn thừa hưởng chỉ một số phương pháp?

Không có phương pháp nào chỉ kế thừa chỉ một hoặc hai phương thức hoặc chức năng từ một lớp nhất định và lý do là chúng ta có thể thừa hưởng toàn bộ lớp và gọi các phương thức hoặc chức năng cần thiết từ lớp đến lớp mà chúng ta cần Chúng tôi chỉ thừa hưởng một hoặc hai phương pháp. and the reason is that we can inherit the entire class and call the needed methods or function from the class to the class in which we need it so why should we inherit only one or two methods.

Bạn có thể thừa hưởng các thuộc tính Python?

Kế thừa là khả năng của một lớp (lớp con/dẫn xuất/phụ) để lấy hoặc kế thừa các thuộc tính hoặc thuộc tính từ một số lớp khác (lớp cha/cơ sở).Kế thừa làm tăng khả năng tái sử dụng của một mã.Chúng ta không cần phải viết cùng một mã nhiều lần. . Inheritance increases reusability of a code. We don't need to write the same code again and again.

Python có hỗ trợ tất cả sự kế thừa không?

Kế thừa là một tính năng cần thiết của mọi ngôn ngữ lập trình hướng đối tượng.Điều này có nghĩa là Python hỗ trợ thừa kế và như bạn sẽ thấy sau này, đó là một trong số ít ngôn ngữ hỗ trợ nhiều kế thừa.Python supports inheritance, and as you'll see later, it's one of the few languages that supports multiple inheritance.

Các lớp con có kế thừa các thuộc tính không?

Một lớp con được thừa hưởng tất cả các thuộc tính (phương thức, v.v.) của lớp cha.Chúng ta có thể tạo các thuộc tính hoặc phương thức mới để thêm vào hành vi của cha mẹ, chúng ta có thể thay đổi (ghi đè lên) một số hoặc tất cả các thuộc tính hoặc phương thức để thay đổi hành vi.. We can create new attributes or methods to add to the behavior of the parent We can change (“override”) some or all of the attributes or methods to change the behavior.