Python: Làm cách nào để tạo lớp con từ lớp cha?


86

Trong Python, làm cách nào để bạn tạo một lớp con từ lớp cha?


3
Lưu ý rằng Python đã thay đổi cách bạn thực hiện phân lớp, vì vậy có 2 cách thực hiện và chúng không kết hợp với nhau. Bạn sẽ gặp lỗi nếu bạn trộn lẫn. Đọc bài đăng này để thấy sự khác biệt: stackoverflow.com/questions/1713038/…
Mark Lakata

Câu trả lời:


89
# Initialize using Parent
#
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

Hoặc, thậm chí tốt hơn, việc sử dụng hàm tích hợp sẵn của Python, super()(xem tài liệu Python 2 / Python 3 về nó) có thể là một phương pháp tốt hơn một chút để gọi hàm cha mẹ để khởi tạo:

# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
    def __init__(self):
        super(MySubClassBetter, self).__init__()

Hoặc, cùng một điều chính xác như trên, ngoại trừ việc sử dụng dạng đối số 0 super(), chỉ hoạt động bên trong định nghĩa lớp:

class MySubClassBetter(MySuperClass):
    def __init__(self):
        super().__init__()

6
OTOH, một số người thận trọng chống lại super, đặc biệt là đối với các lập trình viên Python mới (ví dụ: Lutz). Tôi tránh nó.
eric

6
Lý do duy nhất để tránh superlà nếu bạn không hiểu sự khác biệt giữa cách superhoạt động trong Python và cách super/ parenthoạt động trong các ngôn ngữ khác. Phải thừa nhận rằng điều này không rõ ràng đối với những người đến từ các ngôn ngữ khác, nhưng tôi sẽ không kết luận rằng điều đó đủ điều kiện để "thận trọng chống lại". Nó không làm việc. Nó chỉ hoạt động khác nhau. Chỉ cần đọc về những gì nó thực sự hoạt động trong Python trước khi bạn phàn nàn về việc nhận được kết quả mà bạn không mong đợi.
TheAtomicOption

3
Sự khác biệt giữa hai là gì?
Tiwtiw


65

Một ví dụ nhỏ anh hùng:

class SuperHero(object): #superclass, inherits from default object
    def getName(self):
        raise NotImplementedError #you want to override this on the child classes

class SuperMan(SuperHero): #subclass, inherits from SuperHero
    def getName(self):
        return "Clark Kent"

class SuperManII(SuperHero): #another subclass
    def getName(self):
       return "Clark Kent, Jr."

if __name__ == "__main__":
    sm = SuperMan()
    print sm.getName()
    sm2 = SuperManII()
    print sm2.getName()

37
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

        # <the rest of your custom initialization code goes here>

Các phần thừa kế trong tài liệu python giải thích nó một cách chi tiết hơn


5
Bạn chỉ cần xác định __init__phương thức đó nếu muốn thêm mã khác vào nó, nếu không, phương thức init gốc vẫn được sử dụng (mặc dù nó đáng được đề cập và là mã hoàn toàn hợp lệ)
dbr 22/10/09

2
Tôi nghĩ rằng câu hỏi này đủ mơ hồ để cho rằng có thể có thêm đoạn mã. Tốt hơn hết là cung cấp quá nhiều thông tin còn không đủ và kết thúc bằng một câu hỏi khác khi OP thực hiện nó. :)
Matt Dewey

15
class Class1(object):
    pass

class Class2(Class1):
    pass

Class2 là một lớp con của Class1


Mát mẻ. Đây là những gì tôi thực sự đang tìm kiếm, tức là một lớp con không có phần mở rộng / ghi đè lên lớp siêu.
BuvinJ

9

Trong các câu trả lời ở trên, hàm superđược khởi tạo mà không có bất kỳ đối số (từ khóa) nào. Tuy nhiên, thông thường, bạn muốn làm điều đó, cũng như chuyển một số đối số 'tùy chỉnh' của riêng bạn. Đây là một ví dụ minh họa trường hợp sử dụng này:

class SortedList(list):
    def __init__(self, *args, reverse=False, **kwargs):
        super().__init__(*args, **kwargs)       # Initialize the super class
        self.reverse = reverse
        self.sort(reverse=self.reverse)         # Do additional things with the custom keyword arguments

Đây là một lớp con list, khi được khởi tạo, ngay lập tức tự sắp xếp theo hướng được chỉ định bởi reverseđối số từ khóa, như các thử nghiệm sau minh họa:

import pytest

def test_1():
    assert SortedList([5, 2, 3]) == [2, 3, 5]

def test_2():
    SortedList([5, 2, 3], reverse=True) == [5, 3, 2]

def test_3():
    with pytest.raises(TypeError):
        sorted_list = SortedList([5, 2, 3], True)   # This doesn't work because 'reverse' must be passed as a keyword argument

if __name__ == "__main__":
    pytest.main([__file__])

Nhờ việc chuyển *argssang super, danh sách có thể được khởi tạo và điền các mục thay vì chỉ để trống. (Lưu ý rằng đó reverselà đối số chỉ từ khóa phù hợp với PEP 3102 ).


4

Có một cách khác để tạo động các lớp con trong python bằng một hàm type():

SubClass = type('SubClass', (BaseClass,), {'set_x': set_x})  # Methods can be set, including __init__()

Bạn thường muốn sử dụng phương pháp này khi làm việc với kính đo. Khi bạn muốn thực hiện một số tự động hóa cấp thấp hơn, điều đó sẽ thay đổi cách python tạo lớp. Nhiều khả năng bạn sẽ không cần phải làm theo cách này, nhưng khi bạn làm, bạn sẽ biết mình đang làm gì.





1
class BankAccount:

  def __init__(self, balance=0):
    self.balance = int(balance)

  def checkBalance(self): ## Checking opening balance....
    return self.balance

  def deposit(self, deposit_amount=1000): ## takes in cash deposit amount and updates the balance accordingly.
    self.deposit_amount = deposit_amount
    self.balance += deposit_amount
    return self.balance

  def withdraw(self, withdraw_amount=500): ## takes in cash withdrawal amount and updates the balance accordingly
    if self.balance < withdraw_amount: ## if amount is greater than balance return `"invalid transaction"`
        return 'invalid transaction'
    else:
      self.balance -= withdraw_amount
      return self.balance


class MinimumBalanceAccount(BankAccount): #subclass MinimumBalanceAccount of the BankAccount class

    def __init__(self,balance=0, minimum_balance=500):
        BankAccount.__init__(self, balance=0)
        self.minimum_balance = minimum_balance
        self.balance = balance - minimum_balance
        #print "Subclass MinimumBalanceAccount of the BankAccount class created!"

    def MinimumBalance(self):
        return self.minimum_balance

c = BankAccount()
print(c.deposit(50))
print(c.withdraw(10))

b = MinimumBalanceAccount(100, 50)
print(b.deposit(50))
print(b.withdraw(10))
print(b.MinimumBalance())

5
Câu trả lời này sẽ hữu ích hơn nếu bạn đã bao gồm giải thích về những gì nó làm
grooveplex

4
Mặc dù mã này có thể giúp giải quyết vấn đề, nhưng nó không giải thích tại sao và / hoặc cách nó trả lời câu hỏi. Cung cấp bối cảnh bổ sung này sẽ cải thiện đáng kể giá trị giáo dục lâu dài của nó. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích, bao gồm những giới hạn và giả định nào được áp dụng.
Toby Speight

2
Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
andreas

0

Phân lớp trong Python được thực hiện như sau:

class WindowElement:
    def print(self):
        pass

class Button(WindowElement):
    def print(self):
        pass

Đây là một hướng dẫn về Python cũng chứa các lớp và lớp con.

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.