我們知道Python是一門面向對象的腳本語言。從C#的角度來看:首先Python支持多繼承。Python 類型成員通常都是public的,並且所有成員函數都是virtual的(可以直接重寫)。
1. 定義類型
類是對象的模板,在Python中我們使用class
關鍵字來定義一個類型。
1 # -- coding: utf-8 -- 2 class Employee(object): 3 # self 關鍵字就是對象自身的一個引用(類似於C#中的this關鍵字) 4 def setName(self,name): 5 self.name = name 6 7 def getName(self): 8 return self.name 9 10 def greet(self): 11 print "hello,world! I'm %s" % self.name
可以這樣使用我們定義好的Employee
類:
1 foo = Employee() 2 bob = Employee() 3 foo.setName('Sunshine') 4 bob.setName('Bob') 5 6 foo.greet() # hello,world! I'm Sunshine 7 bob.greet() # hello,world! I'm Bob 8 print foo.name # Sunshine 9 bob.name = 'Bob2' # name是Employee類的一個特性 10 bob.greet() # hello,world! I'm Bob2
1.1 使用新式類型
在Python 2.2之后,對象的工作方式有了很大的改變,所有導致了在Python 2.x 版本中存在兩種形式的類:Python 2.2之前的舊式類,和之后新增的新式類,新式類提供了很多新的特性(比如:super
函數、property
函數等),如果不需要兼容舊版本的Python代碼那么做好使用新式類,在Python中聲明新式類有兩種方法:
1.把賦值語句__metaclass__ = type
放置在定義模塊的最開始位置,如下:
# -- coding: utf-8 -- _metaclass_ = type # 確定使用新式類 class Employee(): pass
2.子類化object
類型,或者是其他新式類型,如下:
class NewStyle(object): pass
2. 特性和成員方法
對象包括特性和方法,特性只是作為對象的一部分的變量,成員方法則是存儲在對象內部的函數。Python中的所有方法函數在聲明時顯式地將第一個參數(self
)表示為對象(實例),這個參數的值在方法被調用時隱式賦值:
1 # -- coding: utf-8 -- 2 _metaclass_ = type # 確定使用新式類 3 4 class Class: 5 def method(self): 6 print 'I have a self' 7 8 def function(): 9 print 'i don\'t...' 10 11 instance = Class() 12 instance.method() # I have a self 13 instance.method = function # 綁定一個普通的函數 14 instance.method() # i don't...
通過self
參數可以使用該實例的所有成員對象:
1 # -- coding: utf-8 -- 2 _metaclass_ = type # 確定使用新式類 3 4 class Bird: 5 song = 'Squaawk!' 6 def sing(self): 7 print self.song 8 9 bird = Bird() 10 bird.sing() # Squaawk!
2.1 私有變量和私有方法
Python其實並不存在不能訪問的私有變量和私有方法。不過在Python中有一個約定:以一個下划線(_)開頭的名字,應該作為一個非公共的API(不論是函數、方法或者數據成員)。我們可以這樣定義一個"私有變量":
_flag = True
Python解釋器在遇到任何以雙下划線(__)開頭的標識符將會被替換為_className__spam
形式,其中className是當前的類型名稱,__spam
就是當前的標識符名稱。所以我們可以這樣定義一個"私有方法":
1 # -- coding: utf-8 -- 2 _metaclass_ = type # 確定使用新式類 3 4 class Secretive: 5 def __inaccessible(self): 6 print 'Bet you can\' see me...' 7 8 def accessible(self): 9 print 'The secret message is:' 10 self.__inaccessible() 11 12 s = Secretive() 13 # AttributeError: Secretive instance has no attribute '__inaccessible' 14 s.__inaccessible()
因為在類的內部定義中,所有以雙下划線開始的名字都被轉換成前面加上單下划線和類名的形式,所以還是可以訪問私有方法:
# Bet you can' see me... s._Secretive__inaccessible()
3. 繼承
作為面向對象三個基本的特性之一———繼承,我們可以利用它在現有類型的基礎上創建自己的類型。在Python中定義派生類的方式如下:
1 # -- coding: utf-8 -- 2 _metaclass_ = type # 確定使用新式類 3 4 class Person: 5 def printName(self): 6 print 'Is a Person' 7 def printHello(self): 8 print 'hello,world' 9 10 class Employee(Person): 11 # override base Method 12 def printName(self): 13 print 'Is a Employee' 14 15 person = Person() 16 person.printName() # Is a Person 17 employee = Employee() 18 employee.printName() # Is a Employee 19 employee.printHello() # hello,world
可以看到子類繼承了基類的方法,由於在Python中所有的成員函數都是virtual的,所有我們也可以選擇重寫基類的方法。
3.1 多重繼承
Python是一個多繼承語言,使用多重繼承的語法很簡單,只需要在定義子類后面的括號中添加多個父類名稱即可,如:
class C(A,B): pass
注意
多重繼承(multiple inheritance)是個很有用的工具。不過除非你特別熟悉多重繼承,否則應該盡量避免使用。因為它可能會有很多出乎意料的行為。例如:一個方法從多個超類繼承,那么根據繼承的順序(class語句中):先繼承的類中的方法會重寫后繼承類中的方法。
3.2 查看繼承關系
Python中有兩個內置函數可擁有查看繼承關系:
- 使用
isinstance
函數檢查實例的類型 - 使用
issubclass
函數檢查類的繼承關系
使用方式如下:
1 # -- coding: utf-8 -- 2 obj = "string" 3 print isinstance(obj,str) # True 4 print obj.__class__ # <type 'str'> 5 6 print issubclass(bool,int) # True 7 print bool.__bases__ # (<type 'int'>,)
3.3 檢查對象中的方法是否存在
使用hasattr(x,'call')
來判斷一個對象是否存在某個方法,如下:
1 # -- coding: utf-8 -- 2 _metaclass_ = type # 確定使用新式類 3 4 class Person: 5 def PrintName(self): 6 print 'Is a Person' 7 def PrintHello(self): 8 print 'hello,world' 9 10 per = Person() 11 12 # check method Exists 13 print hasattr(per,'PrintName') # True