class Account:
def __init__(self, id, name):
self.id = id
self.name = name
self.balance = 0
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
else:
raise ValueError('餘額不足')
def __str__(self):
return ('Id:\t\t' + self.id +
'\nName:\t\t' + self.name +
'\nBalance:\t' + str(self.balance))
在這個類別中,雖然沒有聲明,但你已經使用了繼承,在Python中,所有類別都繼承自object類 別。上例其實相當於:
class
Account(object):
...略
...略
在Python中繼承的語法,是在類別名稱旁使用括號表明要繼承的父類別。例如,你為以上的類別建立了一個支票帳戶:
class CheckingAccount(Account):
def __init__(self, id, name):
super(CheckingAccount, self).__init__(id, name) # 呼叫父類別__init__()
self.overdraftlimit = 30000
def withdraw(self, amount):
if amount <= self.balance + self.overdraftlimit:
self.balance -= amount
else:
raise ValueError('超出信用')
def __str__(self):
return (super(CheckingAccount, self).__str__() +
'\nOverdraft limit\t' + str(self.overdraftlimit));
在上例中,你繼承了Account 來定義一個CheckingAccount子類別。如果在子類別中,需要呼叫父類別的某個方法,則可以使用super()指 定類別名稱與物件,這會將目前實例綁定至所指定父類別方法的第一個引數。
在上例中,你重新定義了withdraw() 與__str__()方法,在操作實例方法時,是從子類別開始尋找是否有定義,否則就搜尋父類別中是否有定義方法。所以:
acct = CheckingAccount('E1234',
'Justin Lin')
print(acct, end='\n\n')
acct.deposit(1000) # 使用 Account 的 deposit() 定義
print(acct, end='\n\n')
acct.withdraw(2000) # 使用 CheckingAccount 的 withdraw() 定義
print(acct, end='\n\n')
print(acct, end='\n\n')
acct.deposit(1000) # 使用 Account 的 deposit() 定義
print(acct, end='\n\n')
acct.withdraw(2000) # 使用 CheckingAccount 的 withdraw() 定義
print(acct, end='\n\n')
在呼叫acct的 deposit()方法時,由於CheckingAccount並沒有定義,所以呼叫的是Account的deposit(),而呼叫 withdraw()時,則是使用CheckingAccount上有定義的withdraw()。
在Python中,可以進行多重繼承,這個時候要注意搜尋的順序,是從子類別開始,接著是同一階層父類別由左至右搜尋,再至更上層同一階層父類別由左 至右搜尋,直到達到頂層為止。例如:
class A(object):
def method1(self):
print('A.method1')
def method2(self):
print('A.method2')
class B(A):
def method3(self):
print('B.method3')
class C(A):
def method2(self):
print('C.method2')
def method3(self):
print('C.method3')
class D(B, C):
def method4(self):
print('D.method4')
d = D()
d.method4() # 在 D 找到,D.method4
d.method3() # 以 D->B 順序找到,B.method3
d.method2() # 以 D->B->C 順序找到,C.method2
d.method1() # 以 D->B->C->A 順序找到,A.method1
在Python中,類別有個__bases__特性,記錄著所繼承的父類別,__bases__是 個 Tuple,有趣的是,你可以改變__bases__來 動態改變繼承的父類別。例如:
>>>
class A:
... def method(self):
... print('A method')
...
>>> class B:
... def method(self):
... print('B method')
...
>>> class C(A):
... pass
...
>>> c = C()
>>> c.method()
A method
>>> C.__bases__
(<class '__main__.A'>,)
>>> C.__bases__ = (B,)
>>> c.method()
B method
>>>
... def method(self):
... print('A method')
...
>>> class B:
... def method(self):
... print('B method')
...
>>> class C(A):
... pass
...
>>> c = C()
>>> c.method()
A method
>>> C.__bases__
(<class '__main__.A'>,)
>>> C.__bases__ = (B,)
>>> c.method()
B method
>>>
在上例中,C原本來繼承自 A類別,透過修改__bases__實際參考的Tuple,C改變繼承B,而尋找特性或方法時,也就改尋找B父類別,因此最後執行的是從B繼承下 來的method()。