一 繼承 基類定義如下:class people:
#define attribute
name = ''
age = 0
#define private attribute
__weight = 0
def __init__(self,n="hello",a=24,w=45.9):
self.name = n
self.age = a
self.__weight = w
def __del__(self):
print("people deconstructor........")
def __repr__(self):
print("people class")
def speak(self):
print("%s is speaking: I am %d years old" % (self.name,self.age))
def weight(self):
print("Weight number:%d" % (self.__weight))
單重繼承class student(people):
grade = ''
def __init__(self,n,a,w,g):
people.__init__(self,n,a,w)
self.grade = g
def speak(self):
print("%s is speaking: I am %d years old,and I am in grade %d" % (self.name,self.age,self.grade))
def __del__(self):
print("student deconstructor......")
s = student('ken',20,60,3)
s.speak()
多重繼承class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("I am %s,I am a speaker!My topic is %s " % (self.name,self.topic))
def __del__(self):
print("speaker deconstructor.....")
class sample(speaker,student):
a = ''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
def __del__(self):
print ('sample deconstructor')
# speaker.__del__()
# student.__del__()
test = sample("Tim",25,80,4,"Python")
test.speak()
需要注意圓括弧中父類的順序,若是父類中有相同的方法名,而在子類使用時未指定,python從左至右搜尋,即方法在子類中未找到時,從左至右尋找父類中是否包含方法。
注意:1. 在Python中,如果父類和子類都重新定義了構造方法__init( )__,在進行子類執行個體化的時候,子類的構造方法不會自動調用父類的構造方法,必須在子類中顯示調用。
2. 如果需要在子類中調用父類的方法,需要以 父類名.方法 這種方式調用,以這種方式調用的時候,注意要傳遞self參數過去。
對於繼承關係,子類繼承了父類所有的公有屬性和方法,可以在子類中通過父類名來調用,而對於私人的屬性和方法,子類是不進行繼承的,因此在子類中是無法通過父類名來訪問的。
Python支援多重繼承。對於多重繼承,比如
class SubClass(SuperClass1,SuperClass2)
此時有一個問題就是如果SubClass沒有重新定義構造方法,它會自動調用哪個父類的構造方法?這裡記住一點:以第一個父類為中心。如果SubClass重新定義了構造方法,需要顯示去調用父類的構造方法,此時調用哪個父類的構造方法由你自己決定;若SubClass沒有重新定義構造方法,則只會執行第一個父類的構造方法。並且若SuperClass1和SuperClass2中有同名的方法,通過子類的執行個體化對象去調用該方法時調用的是第一個父類中的方法。
二 多態
多態即多種形態,在運行時確定其狀態,在編譯階段無法確定其類型,這就是多態。Python中的多態和Java以及C++中的多態有點不同,Python中的變數在定義時不用指明其類型,它會根據需要在運行時確定變數的類型(個人覺得這也是多態的一種體現),並且Python本身是一種解釋性語言,不進行先行編譯,因此它就只在運行時確定其狀態,故也有人說Python是一種多態語言。
在Python中很多地方都可以體現多態的特性,比如內建函數len(object),len函數不僅可以計算字串的長度,還可以計算資料行表、元組等對象中的資料個數,這裡在運行時通過參數類型確定其具體的計算過程,正是多態的一種體現。這有點類似於函數重載(一個編譯單元中有多個同名函數,但參數不同),相當於為每種類型都定義了一個len函數。這是典型的多態表現。有些朋友提出Python不支援多態,我是完全不贊同的。
本質上,多態意味著可以對不同的對象使用同樣的操作,但它們可能會以多種形態呈現出結果。len(object)函數就體現了這一點。在C++、Java、C#這種編譯型語言中,由於有編譯過程,因此就鮮明地分成了運行時多態和編譯時間多態。運行時多態是指允許父類指標或名稱來引用子類對象,或對象方法,而實際調用的方法為對象的類類型方法,這就是所謂的動態綁定。編譯時間多態有模板或範型、方法重載(overload)、方法重寫(override)等。而Python是動態語言,動態地確定類型資訊恰恰體現了多態的特徵。在Python中,任何不知道對象到底是什麼類型,但又需要對象做點什麼的時候,都會用到多態。
能夠直接說明多態的兩段範例程式碼如下:
1、方法多態
[python] view plaincopy
- # -*- coding: UTF-8 -*-
-
- _metaclass_=type # 確定使用新式類
- class calculator:
-
- def count(self,args):
- return 1
-
- calc=calculator() #自訂類型
-
- from random import choice
- obj=choice(['hello,world',[1,2,3],calc]) #obj是隨機返回的 類型不確定
- print type(obj)
- print obj.count('a') #方法多態
對於一個臨時對象obj,它通過Python的隨機函數取出來,不知道具體類型(是字串、元組還是自訂類型),都可以調用count方法進行計算,至於count由誰(哪種類型)去做怎麼去實現我們並不關心。
有一種稱為”鴨子類型(duck typing)“的東西,講的也是多態:
[python] view plaincopy
- _metaclass_=type # 確定使用新式類
- class Duck:
- def quack(self):
- print "Quaaaaaack!"
- def feathers(self):
- print "The duck has white and gray feathers."
-
- class Person:
- def quack(self):
- print "The person imitates a duck."
- def feathers(self):
- print "The person takes a feather from the ground and shows it."
-
- def in_the_forest(duck):
- duck.quack()
- duck.feathers()
-
- def game():
- donald = Duck()
- john = Person()
- in_the_forest(donald)
- in_the_forest(john)
-
- game()
就in_the_forest函數而言,參數對象是一個鴨子類型,它實現了方法多態。但是實際上我們知道,從嚴格的抽象來講,Person類型和Duck完全風馬牛不相及。
2、運算子多態
[python] view plaincopy
- def add(x,y):
- return x+y
-
- print add(1,2) #輸出3
-
- print add("hello,","world") #輸出hello,world
-
- print add(1,"abc") #拋出異常 TypeError: unsupported operand type(s) for +: 'int' and 'str'
上例中,顯而易見,Python的加法運算子是”多態“的,理論上,我們實現的add方法支援任意支援加法的對象,但是我們不用關心兩個參數x和y具體是什麼類型。
Python同樣支援運算子多載,執行個體如下:
[python] view plaincopy
- class Vector:
- def __init__(self, a, b):
- self.a = a
- self.b = b
-
- def __str__(self):
- return 'Vector (%d, %d)' % (self.a, self.b)
-
- def __add__(self,other):
- return Vector(self.a + other.a, self.b + other.b)
-
- v1 = Vector(2,10)
- v2 = Vector(5,-2)
- print v1 + v2
一兩個範例程式碼當然不能從根本上說明多態。普遍認為物件導向最有價值最被低估的特徵其實是多態。我們所理解的多態的實現和子類的虛函數地址綁定有關係,多態的效果其實和函數地址運行時動態綁定有關。在C++, Java, C#中實現多態的方式通常有重寫和重載兩種,從上面兩段代碼,我們其實可以分析得出Python中實現多態也可以變相理解為重寫和重載。在Python中很多內建函數和運算子都是多態的。