python 對象

摘要

經過前面的學習我們已經掌握了內建對象類型(函數 字符串 列表 元祖 字典)

以及內建函數和標準庫的用法,還有定義函數的方法 。


next We are will Study 創建自己的對象(自定義對象)

類型或者叫做類的對象》》這是Python非常核心的概念。As we all known

Python 被稱爲面向對象的語言(SmallTalk 、C++、 Java、)

接下來 我們會介紹如何創建對象,以及多態、封裝、方法、特性、超類以及繼承的概念。

新知識很多,Now We Are Starting .

=========================================================================

對象最重要的優點:

  • 多態:

            意味着可以對不同類的對象使用相同的操作。
    
  • 封裝

            對外部世界隱藏對象的工作細節
    
  • 繼承

    以通用的類爲基礎建立專門的類的對象


術語:多態來自希臘語,意思是“有多種形式”。
多態意味着就算不知道變量所引用的對象類型是什麼,還是能對它進行操作,而它也會根據對象(或類)類型的不同而表現出不同的行爲。
- 讓對象自己進行操作
多態和方法
綁定到對象特性上面的函數稱爲方法(method),

封裝

可以不用關心對象是如何構建的而直接進行使用。

繼承

它是另外一個懶惰(褒義)的行爲。程序員不想把同一段代碼輸入好幾次,

類和類型

類爲種類或類型的同義詞。從很多方面來說,這就是類—一種對象。
所有的對象都屬於一個類,稱爲類的實列(instance)。
鳥類(所有鳥的集合)具有很多子類(百靈鳥類)子類(subclass)
故:鳥類爲百靈鳥類的超類(Superclass)


在面向對象程序設計中,子類的關係是隱式的,因爲一個類的定義取決於它所支持的方法。

類的所有(instance)都會包含這些方法,所以所有子類的所有實列都有這些方法。

定義子類:

只是個定義更多(也有可能是重載已經存在的方法的過程)。

Eg:

Bird(可能支持fly方法),而企鵝類(Penguin)可能會增加個Eatfish的方法。

當創建penguin類時。可能會想重寫(override)超類的fly方法。對於penguin的實列來說,

這個方法要麼什麼也不做,要麼就產生異常(因爲企鵝不會飛)。

區別

在舊版本的python中,內奸的對象是基於類型的,自定義的對象則是基於類的。可以創建類但是不可以創建類型。

最近版本的Python中,遊樂一定變化,基本類型和類之間的界限開始模糊了。可以創建內建類型的子類,而這些類型的行爲更類似於類。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

創建自己的類

先來看一個簡單的類!!

    _metaclass_=type#確定使用新式類
    class Person:
        def setName(self,name):
            self.name=name

            def getName(self):
                return self.name

            def greet(self):
                print ("Hello,world!I'm %s." % self.name)

新式類:需要在模塊或者腳本開始的地方放置賦值語句:

_metaclass_=typepyth3.0之後已不存在舊式類。

接下來讓我們創建一些實列看看:

     foo=Person()
                    bar=Person()
                    foo.setName('ChengKaoAo')
                    bar.setName('MeiXuanZheng')
    ···
>特性、函數和方法
self參數事實上正是方法和函數的區別:
方法(更專業一點可以成爲綁定方法)將它們的第一個參數綁定到所屬的實列上,因此你無需顯示提供參數。當然你也可以將特性綁定到一個普通函數上,這樣就不會有特殊的self參數了。

再論私有化

默認情況下,程序可以從外部訪問一個對象特性。

爲了讓方法或者特性變爲私有(從外部無法訪問),只要在它的名字前面加上雙下劃線即可:

    class Secretive:  
        def __inaccessible(self):  
            print "Bet you can't see me..."  
        def accessible(self):  
            print "The secret message is:"  
            self.__inaccessible()  
    s = Secretive()  
    s.accessible()  

類的命名和空間

所有位於class語句中的代碼都在特殊命名空間執行——類命名空間。這個命名空間可由類內所有成員訪問。並不是所有python程序員都知道類的定義其實就是執行代碼塊

這一點非常有用,比如在類的定義區並不只限定只能使用def語句:

    class C:
        print ('Class C being defined:')
        #繼續>>>
    class MemberCounter:
        members=0
        def init(self):
            MemberCounter.menbers+=1

指定超類

子類可以擴展超類的定義。將其他類名寫在class語句後的圓括號內可以指定超類:

  #_*_ coding:utf8 _*_  
    class Filter:  
        def init(self):  
            self.blocked = []  
        def filter(self,sequence):  
            return [x for x in sequence if x not in self.blocked]  
    class SPAMFilter(Filter):#SPAMFilter是Filter的子類  
        def init(self):#重寫Filter超類中的init方法  
            self.blocked = ['SPAM']  

    f = Filter()  
    f.init()  
    print f.filter([1,2,3])  

    s = SPAMFilter()  
    s.init()  
    print s.filter(['SPAM','SPAM','SPAM','SPAM','eggs','bacon','SPAM']) 

Run Result:

這裏用提供新定義的方式重寫了Filter的init定義。

  • filter方法的定義是從Filter類中拿過來的,所以不用重寫它的定義。

  • 第二個要點就是揭示了繼承的用處:我們可以寫一大堆不同的過濾類,全都從Filter繼承,每一個我都可以使用已經實現的filter方法。

檢查繼承

如果想要查看一個類是否是否是另一個的子類,可以使用內建的issubclass函數:

   # _*_ coding:utf8 _*_
    class Filter:
        def init(self):
            self.blocked = []

        def filter(self, sequence):
            return [x for x in sequence if x not in self.blocked]


    class SPAMFilter(Filter):  # SPAMFilter是Filter的子類
        def init(self):  # 重寫Filter超類中的init方法
            self.blocked = ['SPAM']


    print issubclass(SPAMFilter, Filter)
    print issubclass(Filter, SPAMFilter) 

The Run Result

多個超類

一個類地基類可能會多於一個,EG:

子類(TalkingCalculator)自己不做任何事,它從自己的超類繼承所有的行爲。

它從Calculator類哪裏繼承Calculate方法,從Talke類哪裏繼承talk方法,這樣它就成了會說話的

計算器(talking calculator)

這種行爲叫做多重繼承。除非非常熟悉,否則應儘量避免使用,因爲有時會出現不可預見的麻煩,

    # _*_ coding:utf8 _*_
    class Calculator:
        def calculate(self,expression):
            self.value = eval(expression)
            class Talker:
                def talk(self):
                    print 'Hi,my value is',self.value

                    class TalkingCalculator(Calculator, Talker):
                        pass

                    tc = TalkingCalculator()
                    tc.calculate('1+2*3+1')
                    tc.talk()

當有2個相同名字的不同方法時,需要注意超類的順序(在Class語句中),先繼承的類中的方法會重寫後繼承的類中的方法,

接口和內省

“接口”的概念與多態有關。

  • 在處理多態對象時,只要關心他的接口(或稱“協議”)即可,也就是公開的方法和特徵。

  • 在Python中,不用顯式地指定對象必須包含哪些方法才能作爲參數接收。
    一般來說只需要讓對象符合當前的接口(就是實現當前的方法),但是還可以更靈活一些。
    除了調用方法然後期待一切順利之外,還可檢查所需方法是否已經存在。


關於面向對象的思考

要點:

  • 將屬於一類的對象放在一起。如果一個函數操縱一個全局變量,那麼兩者最好都在類內作爲特徵和方法出現。

  • 不要讓對象過於親密。方法應該只關心自己實例的特徵。讓其他實例管理自己的狀態。

  • 要小心繼承,尤其是多重繼承。繼承機制有時很有用,但也會在某些情況下讓事情變得過於複雜。多繼承難以正確使用,更難以調試。
  • 簡單就好。讓你的方法小巧。一般來說,多數方法都應該在30秒內被讀完(以及理解),儘量將代碼行數控制在一頁或者一屏之內。

當考慮需要什麼類以及類要有什麼方法時,應該嘗試下面的方法。

(1)寫下問題的描述(程序要做什麼),把所有名詞、動詞、形容詞加下劃線

(2)對於所有名詞,用作可能的類。

(3)對於所有動詞,用作可能的方法。

(4)對於所有形容詞,用作可能的特性。

(5)把所有方法特性分配到類。

現在已經有了面向對象模型的草圖了,還可以考慮類和對象之間的關係(比如繼承或協作)

以及它們的作用,可以用以下步驟精煉模型。

(1)寫下(想象)一系列使用實列,也就是程序應用時的場景,試着包括所有的功能。

(2)一步步考慮每個使用實列,保證每個模型包括所有需要的東西,如果有遺漏的話就添加進來,

如果某處不太正確則改正。繼續,到滿意爲止。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章