2009-10-22 69 views
54

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

+3

Lưu ý rằng Python đã thay đổi cách bạn làm lớp con, vì vậy có 2 cách để thực hiện và không trộn lẫn. Bạn sẽ gặp lỗi nếu bạn trộn. Đọc bài đăng này để xem sự khác biệt: http: // stackoverflow.com/questions/1713038/super-fail-với-lỗi-typeerror-argument-1-must-be-type-not-classobj –

Trả lời

1
class Subclass (SuperClass): 
     # Subclass stuff here 
8
class Class1(object): 
    pass 

class Class2(Class1): 
    pass 

Class2 là một sub-class của Class1

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

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

Các section on inheritance trong tài liệu python giải thích nó một cách chi tiết hơn

+2

Bạn chỉ cần xác định phương thức '__init__' nếu muốn thêm mã vào nó, nếu không phương pháp init ban đầu được sử dụng anyway (mặc dù nó đáng nói đến, và là mã hoàn toàn hợp lệ) – dbr

+2

Tôi nghĩ rằng câu hỏi là mơ hồ, đủ để giả sử có thể có thêm mã. Tốt hơn là cung cấp quá nhiều thông tin hơn là không đủ và kết thúc với một câu hỏi khác khi OP triển khai nó. :) –

2
class Mammal(object): 
#mammal stuff 

class Dog(Mammal): 
#doggie stuff 
0

subclassing bằng 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 tutorial về Python cũng chứa các lớp và các lớp con.

50

Một chút anh hùng ví dụ:

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

yeay để sử dụng tên cụ thể để làm cho một khái niệm dễ tiêu hóa hơn! –

60

Việc sử dụng "siêu" (xem Python Built-in, siêu) có thể là một phương pháp tốt hơn một chút gọi phụ huynh để khởi tạo:

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

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

OTOH, một số người cảnh báo 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ó. – neuronet

+0

Lý do duy nhất để tránh 'super' là nếu bạn không hiểu sự khác biệt giữa cách' super' hoạt động trong Python và cách 'super' /' parent' hoạt động với 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 để làm điều gì đó để "thận trọng chống lại". Nó * làm * làm việc. Nó chỉ hoạt động khác nhau. Chỉ cần đọc về những gì nó thực sự làm 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

2

Có một cách khác để tạo các lớp con trong python động với 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 metaclasses. Khi bạn muốn làm một số tự động hóa mức thấp hơn, làm thay đổi cách python tạo lớp. Nhiều khả năng bạn sẽ không bao giờ cần phải làm điều đó theo cách này, nhưng khi bạn làm, hơn bạn đã biết bạn đ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()) 
+4

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

+3

Mặc dù mã này có thể giúp giải quyết vấn đề, nó không giải thích _why_ và/hoặc _how_ nó trả lời câu hỏi. Việc cung cấp ngữ 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 [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 được áp dụng. –

+2

Khi đoạn mã này có thể giải quyết được câu hỏi, [bao gồm cả giải thích] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) 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

2

Trong câu trả lời ở trên, 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ư truyền một số đối số 'tùy chỉnh' của riêng bạn. Dưới đâ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 của list mà khi khởi tạo, ngay lập tức sắp xếp bản thân theo hướng quy định bởi đối số reverse từ khóa, như các bài kiểm tra sau đây 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ờ sự chuyển giao của *args đến super, danh sách có thể được khởi tạo và được điền bằng các mục thay vì chỉ trống. (Lưu ý rằng reverse là đối số chỉ từ khoá theo PEP 3102).

Các vấn đề liên quan