Python物件導向特徵總結

來源:互聯網
上載者:User

抽象是隱藏多餘細節的藝術。在物件導向的概念中,抽象的直接表現形式通常為類。Python基本上提供了物件導向程式設計語言的所有元素,如果你已經至少掌握了一門物件導向語言,那麼利用Python進行物件導向程式設計將會相當容易。

一、封裝

物件導向程式設計中的術語對象(Object)基本上可以看做資料(特性)以及由一系列可以存取、操作這些資料的方法所組成的集合。傳統意義上的“程式=資料結構+演算法”被封裝”掩蓋“並簡化為“程式=對象+訊息”。對象是類的執行個體,類的抽象則需要經過封裝。封裝可以讓調用者不用關心對象是如何構建的而直接進行使用。

一個簡單的Python類封裝如下:

Encapsulation_metaclass_=type # 確定使用新式類class Animal:    def __init__(self): #構造方法 一個對象建立後會立即調用此方法        self.Name="Doraemon"        print self.Name          def accessibleMethod(self): #Binder 方法 對外公開        print "I have a self! current name is:"        print self.Name        print "the secret message is:"        self.__inaccessible()            def __inaccessible(self): #私人方法 對外不公開 以雙底線開頭        print "U cannot see me..."    @staticmethod    def staticMethod():        #self.accessibleMethod() #在靜態方法中無法直接調用執行個體方法 直接拋出異常        print "this is a static method"    def setName(self,name): #訪問器函數        self.Name=name    def getName(self): #訪問器函數        return self.Name    name=property(getName,setName) #屬性 可讀可寫

 

上面簡單的範例程式碼可以看出,Python中的類包含了一般物件導向程式設計語言的主要元素,比如構造方法、Binder 方法、靜態方法、屬性等,如果深入下去,還可以發現Python中內建了很多物件導向的“進階”主題,比如迭代器、反射、特性等等,提供了封裝的直接構造要素。

 

二、繼承1、類繼承

繼承給人的直接感覺是這是一種複用代碼的行為。繼承可以理解為它是以普通的類為基礎建立專門的類對象,子類和它繼承的父類是IS-A的關係。一個簡單而不失經典的樣本如下:

Inheritance_metaclass_=type # 確定使用新式類class Animal:    def __init__(self):         self.Name="Animal"          def move(self,meters):        print "%s moved %sm." %(self.Name,meters)         class Cat(Animal): #Cat是Animal的子類     def __init__(self):  #重寫超類的構造方法        self.Name="Garfield"##     def move(self,meters): #重寫超類的Binder 方法##        print "Garfield never moves more than 1m."class RobotCat(Animal):    def __init__(self):  #重寫超類的構造方法        self.Name="Doraemon"##     def move(self,meters): #重寫超類的Binder 方法##        print "Doraemon is flying."obj=Animal()obj.move(10) #輸出:Animal moved 10m.cat=Cat()cat.move(1) #輸出:Garfield moved 1m.robot=RobotCat()robot.move(1000) #輸出:Doraemon moved 1000m.

 

一個顯而易見的特點是,Python的物件導向的繼承特徵是基於類(class)的,比javascript基於原型(prototype)的繼承更容易組織和編寫代碼,也更容易讓人接受和理解。

ps:最近幾天Anders大神搞出來的TypeScript橫空出世,看它的語言規範裡繼承也是基於類的:

TypeScript-SimpleInheritanceclass Animal {    constructor(public name) { }    move(meters) {        alert(this.name + " moved " + meters + "m.");    }}class Snake extends Animal {    constructor(name) { super(name); }    move() {        alert("Slithering...");        super.move(5);    }}class Horse extends Animal {    constructor(name) { super(name); }    move() {        alert("Galloping...");        super.move(45);    }}var sam = new Snake("Sammy the Python")var tom: Animal = new Horse("Tommy the Palomino")sam.move()tom.move(34)

 

感覺基於類的繼承的語言好像在實現OO的可讀性和編程體驗上都不太差,據傳說javascript是碼農最想噴也是噴過最多f**k的語言。

2、多重繼承

不同於C#,Python是支援多重類繼承的(C#可繼承自多個Interface,但最多繼承自一個類)。多重繼承機制有時很好用,但是它容易讓事情變得複雜。一個多重繼承的樣本如下:

MultInheritance_metaclass_=type # 確定使用新式類class Animal:      def eat(self,food):        print "eat %s" %food         class Robot:          def fly(self,kilometers):        print "flyed %skm." %kilometers         class RobotCat(Animal,Robot): #繼承自多個超類    def __init__(self):          self.Name="Doraemon"robot=RobotCat() # 一隻可以吃東西的會飛行的叫哆啦A夢的機器貓print robot.Namerobot.eat("cookies") #從動物繼承而來的eatrobot.fly(10000000) #從機器繼承而來的fly

 

如你所看到的那樣,多重繼承的好處顯而易見,我們可以輕而易舉地通過類似“組合”的方式複用代碼構造一個類型。

有個需要注意的地方,即如果一個方法從多個超類繼承,那麼務必要小心繼承的超類(或者基類)的順序:

MultInheritance_metaclass_=type # 確定使用新式類class Animal:      def eat(self,food):        print "eat %s" %food    def move(self,kilometers): #動物的move方法        pass        class Robot:          def move(self,kilometers): #機器的move方法        print "flyed %skm." %kilometers         class RobotCat(Animal,Robot): #繼承自多個超類 如方法名稱相同,注意繼承的順序#class RobotCat(Robot,Animal):     def __init__(self):          self.Name="Doraemon"robot=RobotCat() # 一隻可以吃東西的會飛行的叫哆啦A夢的機器貓print robot.Namerobot.eat("cookies") #從動物繼承而來的eatrobot.move(10000000) #本來是要從機器繼承move方法,但是因為繼承的順序,這個方法直接繼承自動物而pass掉

 

我們為動物和機器各實現一個相同名稱的move方法,但是輸出因為繼承的順序而有所不同,Python在尋找給定方法或者特性時訪問超類的順序被稱為MRO(Method Resolution Order,方法判定順序)。

三、多態

多態意味著可以對不同的對象使用同樣的操作,但它們可能會以多種形態呈現出結果。在Python中,任何不知道對象到底是什麼類型,但又需要對象做點什麼的時候,都會用到多態。

能夠直接說明多態的兩段範例程式碼如下:

1、方法多態
Method-Polymorphism_metaclass_=type # 確定使用新式類class calculator:      def count(self,args):        return 1calc=calculator() #自訂類型from random import choiceobj=choice(['hello,world',[1,2,3],calc]) #obj是隨機返回的 類型不確定#print type(obj)print obj.count('a') #方法多態

 

對於一個臨時對象obj,它通過Python的隨機函數取出來,不知道具體類型(是字串、元組還是自訂類型),都可以調用count方法進行計算,至於count由誰(哪種類型)去做怎麼去實現我們並不關心。

有一種稱為”鴨子類型(duck typing)“的東西,講的也是多態:

DuckTyping_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、運算子也多態
Operator-Polymorphismdef add(x,y):    return x+yprint add(1,2) #輸出3print add("hello,","world") #輸出hello,worldprint add(1,"abc") #拋出異常 TypeError: unsupported operand type(s) for +: 'int' and 'str'

 

上例中,顯而易見,Python的加法運算子是”多態“的,理論上,我們實現的add方法支援任意支援加法的對象,但是我們不用關心兩個參數x和y具體是什麼類型。

一兩個範例程式碼當然不能從根本上說明多態。普遍認為物件導向最有價值最被低估的特徵其實是多態。我們所理解的多態的實現和子類的虛函數地址綁定有關係,多態的效果其實和函數地址運行時動態綁定有關。在C#中實現多態的方式通常有重寫和重載兩種,從上面兩段代碼,我們其實可以分析得出Python中實現多態也可以變相理解為重寫和重載。在Python中很多內建函數和運算子都是多態的。

號外:在C#中,我們熟知介面(Interface)和多態相關,在處理多態對象時,只要關心它的介面(或者稱為“協議”)而不需要顯式指定特定實作類別型即可,這也是IoC中面向介面(抽象)而不依賴於具體實現編程的基礎。可惜在Python中根本沒有Interface(有抽象類別)。而在TypeScript的Specification中引入了Interface的概念:

TypeScript-Interfaceinterface Friend {    name: string;    favoriteColor?: string;}function add(friend: Friend) {    var name = friend.name;}add({ name: "Fred" });  // Okadd({ favoriteColor: "blue" });  // Error, name requiredadd({ name: "Jill", favoriteColor: "green" });  // Ok

 

TypeScript語言規範裡對Interface的定義是命名的物件類型(Programmers can give names to object types; we call named object types interfaces. )。它直接等價於下面的Ojbect Type:

var Friend: () => {    name: string; favoriteColor?: string;};

上面這個Object Type在Playgound中等價的javascript代碼如下:

var Friend;

在TypeScript編程規範文檔裡,對Interface的一些說明:

Interfaces provide the ability to give names to object types and the ability to compose existing named object types into new ones.
Interfaces have no run-time representation—they are purely a compile-time construct. Interfaces are particularly useful for documenting and validating the required shape of properties, objects passed as parameters, and objects returned from functions
.

Interface可以繼承自Interface:

TypeScript-InterfaceInheritInterfaceinterface Mover{    move(): void;    getStatus(): { speed: number; };}interface Shaker{    shake(): void;    getStatus(): { frequency: number; };}interface SimpleMover extends Mover{}interface MoverShaker extends Mover, Shaker{    getStatus(): { speed: number; frequency: number; };}

 

我們嘗試讓類繼承自Interface:

TypeScript-ClassInheritInterfaceinterface Mover{    move(): void;}class SimpleMover  extends Mover{    move() {alert("move")    }}var mover=new SimpleMover();mover.move();

 

實踐證明類是不能繼承實現Interface的:A export class may only extend other classes, Mover is an interface.

現在大家知道TypeScript裡的Interface和我們所認識和理解的介面的區別了嗎?相同的一個名詞Interface,不同語境下意義並不完全相同,看上去好像是挺傻的,但是學習和使用語言不做對比幾乎是不可能的。

 

參考:

http://www.python.org/

http://zh.wikipedia.org/wiki/Duck_typing

http://typescript.codeplex.com/

http://www.typescriptlang.org/Playground/

http://www.nczonline.net/blog/2012/10/04/thoughts-on-typescript/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.