在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 面向?qū)ο蟮木幊?/span>
備份腳本——版本四
使用 <strong>init</strong> 方法
控制流
異常
表 15.1 一些特殊的方法
如何創(chuàng)建你自己的模塊
使用字典
前言
使用默認(rèn)參數(shù)值
表 5.1 運(yùn)算符與它們的用法
解決問(wèn)題——編寫(xiě)一個(gè) Python 腳本
使用 for 語(yǔ)句
使用 continue 語(yǔ)句
使用元組輸出
對(duì)象與參考
使用函數(shù)形參
使用默認(rèn)參數(shù)值
使用 if 語(yǔ)句
如何引發(fā)異常
使用源文件
使用對(duì)象的方法
使用表達(dá)式
定義函數(shù)
使用局部變量
使用列表綜合
使用 sys.argv
使用 lambda 形式
使用 global 語(yǔ)句
備份腳本——版本二
使用列表
使用 while 語(yǔ)句
備份腳本——版本一
使用元組
輸入/輸出
使用類與對(duì)象的變量
使用 sys 模塊
表 5.2 運(yùn)算符優(yōu)先級(jí)
處理異常
使用 break 語(yǔ)句
函數(shù)
基本概念
運(yùn)算符與表達(dá)式
介紹
使用文件
使用序列
接下來(lái)學(xué)習(xí)什么?
使用帶提示符的 Python 解釋器
使用 DocStrings
使用字面意義上的語(yǔ)句
最初的步驟
數(shù)據(jù)結(jié)構(gòu)
儲(chǔ)存與取儲(chǔ)存
使用 dir 函數(shù)
模塊
Python 標(biāo)準(zhǔn)庫(kù)
備份腳本——版本三(不工作?。?/span>
創(chuàng)建一個(gè)類
安裝 Python
面向?qū)ο蟮木幊?/span>
使用模塊的<strong>name</strong>
使用變量和字面意義上的常量
使用繼承

面向?qū)ο蟮木幊?/h1>

簡(jiǎn)介

到目前為止,在我們的程序中,我們都是根據(jù)操作數(shù)據(jù)的函數(shù)或語(yǔ)句塊來(lái)設(shè)計(jì)程序的。這被稱為 面向過(guò)程的 編程。還有一種把數(shù)據(jù)和功能結(jié)合起來(lái),用稱為對(duì)象的東西包裹起來(lái)組織程序的方法。這種方法稱為 面向?qū)ο蟮?/em> 編程理念。在大多數(shù)時(shí)候你可以使用過(guò)程性編程,但是有些時(shí)候當(dāng)你想要編寫(xiě)大型程序或是尋求一個(gè)更加合適的解決方案的時(shí)候,你就得使用面向?qū)ο蟮木幊碳夹g(shù)。

類和對(duì)象是面向?qū)ο缶幊痰膬蓚€(gè)主要方面。類創(chuàng)建一個(gè)新類型,而對(duì)象這個(gè)類的 實(shí)例 。這類似于你有一個(gè) int 類型的變量,這存儲(chǔ)整數(shù)的變量是 int 類的實(shí)例(對(duì)象)。

給 C/C++/Java/C#程序員的注釋
注意,即便是整數(shù)也被作為對(duì)象(屬于 int 類)。這和 C++、Java(1.5 版之前)把整數(shù)純粹作為類型是不同的。通過(guò) help(int)了解更多這個(gè)類的詳情。 C#和 Java 1.5 程序員會(huì)熟悉這個(gè)概念,因?yàn)樗愃婆c 封裝與解封裝 的概念。

對(duì)象可以使用普通的 屬于 對(duì)象的變量存儲(chǔ)數(shù)據(jù)。屬于一個(gè)對(duì)象或類的變量被稱為。對(duì)象也可以使用屬于 類的函數(shù)來(lái)具有功能。這樣的函數(shù)被稱為類的方法。這些術(shù)語(yǔ)幫助我們把它們與孤立的函數(shù)和變量區(qū)分開(kāi)來(lái)。域和方法可以合稱為類的屬性。

域有兩種類型——屬于每個(gè)實(shí)例/類的對(duì)象或?qū)儆陬惐旧?。它們分別被稱為實(shí)例變量類變量。

類使用 class 關(guān)鍵字創(chuàng)建。類的域和方法被列在一個(gè)縮進(jìn)塊中。

self

類的方法與普通的函數(shù)只有一個(gè)特別的區(qū)別——它們必須有一個(gè)額外的第一個(gè)參數(shù)名稱,但是在調(diào)用這個(gè)方法的時(shí)候你不為這個(gè)參數(shù)賦值,Python 會(huì)提供這個(gè)值。這個(gè)特別的變量指對(duì)象本身,按照慣例它的名稱是 self。

雖然你可以給這個(gè)參數(shù)任何名稱,但是 強(qiáng)烈建議 你使用 self 這個(gè)名稱——其他名稱都是不贊成你使用的。使用一個(gè)標(biāo)準(zhǔn)的名稱有很多優(yōu)點(diǎn)——你的程序讀者可以迅速識(shí)別它,如果使用 self 的話,還有些 IDE(集成開(kāi)發(fā)環(huán)境)也可以幫助你。

給 C++/Java/C#程序員的注釋
Python 中的 self 等價(jià)于 C++中的 self 指針和 Java、C#中的 this 參考。

你一定很奇怪 Python 如何給 self 賦值以及為何你不需要給它賦值。舉一個(gè)例子會(huì)使此變得清晰。假如你有一個(gè)類稱為 MyClass 和這個(gè)類的一個(gè)實(shí)例 MyObject。當(dāng)你調(diào)用這個(gè)對(duì)象的方法 MyObject.method(arg1, arg2)的時(shí)候,這會(huì)由 Python 自動(dòng)轉(zhuǎn)為 MyClass.method(MyObject, arg1, arg2)——這就是 self 的原理了。

這也意味著如果你有一個(gè)不需要參數(shù)的方法,你還是得給這個(gè)方法定義一個(gè) self 參數(shù)。

一個(gè)盡可能簡(jiǎn)單的類如下面這個(gè)例子所示。

創(chuàng)建一個(gè)類

例 11.1 創(chuàng)建一個(gè)類


    #!/usr/bin/python
    # Filename: simplestclass.py

    class Person:
        pass # An empty block

    p = Person()
    print p

(源文件:code/simplestclass.py

輸出


    $ python simplestclass.py
    <__main__.Person instance at 0xf6fcb18c>

它如何工作

我們使用 class 語(yǔ)句后跟類名,創(chuàng)建了一個(gè)新的類。這后面跟著一個(gè)縮進(jìn)的語(yǔ)句塊形成類體。在這個(gè)例子中,我們使用了一個(gè)空白塊,它由 pass 語(yǔ)句表示。

接下來(lái),我們使用類名后跟一對(duì)圓括號(hào)來(lái)創(chuàng)建一個(gè)對(duì)象/實(shí)例。(我們將在下面的章節(jié)中學(xué)習(xí)更多的如何創(chuàng)建實(shí)例的方法)。為了驗(yàn)證,我們簡(jiǎn)單地打印了這個(gè)變量的類型。它告訴我們我們已經(jīng)在main模塊中有了一個(gè) Person 類的實(shí)例。

可以注意到存儲(chǔ)對(duì)象的計(jì)算機(jī)內(nèi)存地址也打印了出來(lái)。這個(gè)地址在你的計(jì)算機(jī)上會(huì)是另外一個(gè)值,因?yàn)?Python 可以在任何空位存儲(chǔ)對(duì)象。

對(duì)象的方法

我們已經(jīng)討論了類/對(duì)象可以擁有像函數(shù)一樣的方法,這些方法與函數(shù)的區(qū)別只是一個(gè)額外的 self 變量?,F(xiàn)在我們來(lái)學(xué)習(xí)一個(gè)例子。

使用對(duì)象的方法

例 11.2 使用對(duì)象的方法


    #!/usr/bin/python
    # Filename: method.py

    class Person:
        def sayHi(self):
            print 'Hello, how are you?'

    p = Person()
    p.sayHi()

    # This short example can also be written as Person().sayHi()

(源文件:code/method.py

輸出


    $ python method.py
    Hello, how are you?

它如何工作

這里我們看到了 self 的用法。注意 sayHi 方法沒(méi)有任何參數(shù),但仍然在函數(shù)定義時(shí)有 self。

init 方法

在 Python 的類中有很多方法的名字有特殊的重要意義?,F(xiàn)在我們將學(xué)習(xí) init 方法的意義。

init 方法在類的一個(gè)對(duì)象被建立時(shí),馬上運(yùn)行。這個(gè)方法可以用來(lái)對(duì)你的對(duì)象做一些你希望的 初始化 。注意,這個(gè)名稱的開(kāi)始和結(jié)尾都是雙下劃線。

使用 init 方法

例 11.3 使用 init 方法


    #!/usr/bin/python
    # Filename: class_init.py

    class Person:
        def __init__(self, name):
            self.name = name
        def sayHi(self):
            print 'Hello, my name is', self.name

    p = Person('Swaroop')
    p.sayHi()

    # This short example can also be written as Person('Swaroop').sayHi()

(源文件:code/class_init.py

輸出


    $ python class_init.py
    Hello, my name is Swaroop

它如何工作

這里,我們把 init 方法定義為取一個(gè)參數(shù) name(以及普通的參數(shù) self)。在這個(gè) init 里,我們只是創(chuàng)建一個(gè)新的域,也稱為 name。注意它們是兩個(gè)不同的變量,盡管它們有相同的名字。點(diǎn)號(hào)使我們能夠區(qū)分它們。

最重要的是,我們沒(méi)有專門調(diào)用 init 方法,只是在創(chuàng)建一個(gè)類的新實(shí)例的時(shí)候,把參數(shù)包括在圓括號(hào)內(nèi)跟在類名后面,從而傳遞給 init 方法。這是這種方法的重要之處。

現(xiàn)在,我們能夠在我們的方法中使用 self.name 域。這在 sayHi 方法中得到了驗(yàn)證。

給 C++/Java/C#程序員的注釋
init 方法類似于 C++、C#和 Java 中的 constructor

類與對(duì)象的變量

我們已經(jīng)討論了類與對(duì)象的功能部分,現(xiàn)在我們來(lái)看一下它的數(shù)據(jù)部分。事實(shí)上,它們只是與類和對(duì)象的名稱空間 綁定 的普通變量,即這些名稱只在這些類與對(duì)象的前提下有效。

有兩種類型的 ——類的變量和對(duì)象的變量,它們根據(jù)是類還是對(duì)象 擁有 這個(gè)變量而區(qū)分。

類的變量 由一個(gè)類的所有對(duì)象(實(shí)例)共享使用。只有一個(gè)類變量的拷貝,所以當(dāng)某個(gè)對(duì)象對(duì)類的變量做了改動(dòng)的時(shí)候,這個(gè)改動(dòng)會(huì)反映到所有其他的實(shí)例上。

對(duì)象的變量 由類的每個(gè)對(duì)象/實(shí)例擁有。因此每個(gè)對(duì)象有自己對(duì)這個(gè)域的一份拷貝,即它們不是共享的,在同一個(gè)類的不同實(shí)例中,雖然對(duì)象的變量有相同的名稱,但是是互不相關(guān)的。通過(guò)一個(gè)例子會(huì)使這個(gè)易于理解。

使用類與對(duì)象的變量

例 11.4 使用類與對(duì)象的變量


    #!/usr/bin/python
    # Filename: objvar.py

    class Person:
         '''Represents a person.'''
        population = 0

        def __init__(self, name):
            '''Initializes the person's data.'''
            self.name = name
            print '(Initializing %s)' % self.name

            # When this person is created, he/she
            # adds to the population
            Person.population += 1

        def __del__(self):
            '''I am dying.'''
             print '%s says bye.' % self.name

            Person.population -= 1

            if Person.population == 0:
                print 'I am the last one.'
            else:
                print 'There are still %d people left.' % Person.population

        def sayHi(self):
            '''Greeting by the person.

            Really, that's all it does.'''
            print 'Hi, my name is %s.' % self.name

        def howMany(self):
            '''Prints the current population.'''
             if Person.population == 1:
                 print 'I am the only person here.'
            else:
                print 'We have %d persons here.' % Person.population

    swaroop = Person('Swaroop')
    swaroop.sayHi()
    swaroop.howMany()

    kalam = Person('Abdul Kalam')
    kalam.sayHi()
    kalam.howMany()

    swaroop.sayHi()
    swaroop.howMany()

(源文件:code/objvar.py

輸出


    $ python objvar.py
    (Initializing Swaroop)
    Hi, my name is Swaroop.
    I am the only person here.
    (Initializing Abdul Kalam)
    Hi, my name is Abdul Kalam.
    We have 2 persons here.
    Hi, my name is Swaroop.
    We have 2 persons here.
    Abdul Kalam says bye.
    There are still 1 people left.
    Swaroop says bye.
    I am the last one.

它如何工作

這是一個(gè)很長(zhǎng)的例子,但是它有助于說(shuō)明類與對(duì)象的變量的本質(zhì)。這里,population 屬于 Person 類,因此是一個(gè)類的變量。name 變量屬于對(duì)象(它使用 self 賦值)因此是對(duì)象的變量。

觀察可以發(fā)現(xiàn) init 方法用一個(gè)名字來(lái)初始化 Person 實(shí)例。在這個(gè)方法中,我們讓 population 增加 1,這是因?yàn)槲覀冊(cè)黾恿艘粋€(gè)人。同樣可以發(fā)現(xiàn),self.name 的值根據(jù)每個(gè)對(duì)象指定,這表明了它作為對(duì)象的變量的本質(zhì)。

記住,你只能使用 self 變量來(lái)參考同一個(gè)對(duì)象的變量和方法。這被稱為 屬性參考 。

在這個(gè)程序中,我們還看到 docstring 對(duì)于類和方法同樣有用。我們可以在運(yùn)行時(shí)使用 Person.doc 和 Person.sayHi.doc 來(lái)分別訪問(wèn)類與方法的文檔字符串。

就如同 init 方法一樣,還有一個(gè)特殊的方法del,它在對(duì)象消逝的時(shí)候被調(diào)用。對(duì)象消逝即對(duì)象不再被使用,它所占用的內(nèi)存將返回給系統(tǒng)作它用。在這個(gè)方法里面,我們只是簡(jiǎn)單地把 Person.population 減 1。

當(dāng)對(duì)象不再被使用時(shí), del 方法運(yùn)行,但是很難保證這個(gè)方法究竟在 什么時(shí)候 運(yùn)行。如果你想要指明它的運(yùn)行,你就得使用 del 語(yǔ)句,就如同我們?cè)谝郧暗睦又惺褂玫哪菢印?/p>

給 C++/Java/C#程序員的注釋
Python 中所有的類成員(包括數(shù)據(jù)成員)都是 公共的 ,所有的方法都是 有效的 。 只有一個(gè)例外:如果你使用的數(shù)據(jù)成員名稱以 雙下劃線前綴 比如 privatevar,Python 的名稱管理體系會(huì)有效地把它作為私有變量。 這樣就有一個(gè)慣例,如果某個(gè)變量只想在類或?qū)ο笾惺褂?,就?yīng)該以單下劃線前綴。而其他的名稱都將作為公共的,可以被其他類/對(duì)象使用。記住這只是一個(gè)慣例,并不是 Python 所要求的(與雙下劃線前綴不同)。 同樣,注意 del__ 方法與 destructor 的概念類似。

繼承

面向?qū)ο蟮木幊處?lái)的主要好處之一是代碼的重用,實(shí)現(xiàn)這種重用的方法之一是通過(guò) 繼承 機(jī)制。繼承完全可以理解成類之間的 類型和子類型 關(guān)系。

假設(shè)你想要寫(xiě)一個(gè)程序來(lái)記錄學(xué)校之中的教師和學(xué)生情況。他們有一些共同屬性,比如姓名、年齡和地址。他們也有專有的屬性,比如教師的薪水、課程和假期,學(xué)生的成績(jī)和學(xué)費(fèi)。

你可以為教師和學(xué)生建立兩個(gè)獨(dú)立的類來(lái)處理它們,但是這樣做的話,如果要增加一個(gè)新的共有屬性,就意味著要在這兩個(gè)獨(dú)立的類中都增加這個(gè)屬性。這很快就會(huì)顯得不實(shí)用。

一個(gè)比較好的方法是創(chuàng)建一個(gè)共同的類稱為 SchoolMember 然后讓教師和學(xué)生的類 繼承 這個(gè)共同的類。即它們都是這個(gè)類型(類)的子類型,然后我們?cè)贋檫@些子類型添加專有的屬性。

使用這種方法有很多優(yōu)點(diǎn)。如果我們?cè)黾?改變了 SchoolMember 中的任何功能,它會(huì)自動(dòng)地反映到子類型之中。例如,你要為教師和學(xué)生都增加一個(gè)新的身份證域,那么你只需簡(jiǎn)單地把它加到 SchoolMember 類中。然而,在一個(gè)子類型之中做的改動(dòng)不會(huì)影響到別的子類型。另外一個(gè)優(yōu)點(diǎn)是你可以把教師和學(xué)生對(duì)象都作為 SchoolMember 對(duì)象來(lái)使用,這在某些場(chǎng)合特別有用,比如統(tǒng)計(jì)學(xué)校成員的人數(shù)。一個(gè)子類型在任何需要父類型的場(chǎng)合可以被替換成父類型,即對(duì)象可以被視作是父類的實(shí)例,這種現(xiàn)象被稱為多態(tài)現(xiàn)象。

另外,我們會(huì)發(fā)現(xiàn)在 重用 父類的代碼的時(shí)候,我們無(wú)需在不同的類中重復(fù)它。而如果我們使用獨(dú)立的類的話,我們就不得不這么做了。

在上述的場(chǎng)合中,SchoolMember 類被稱為 基本類超類 。而 Teacher 和 Student 類被稱為 導(dǎo)出類子類 。

現(xiàn)在,我們將學(xué)習(xí)一個(gè)例子程序。

使用繼承

例 11.5 使用繼承


    #!/usr/bin/python
    # Filename: inherit.py

    class SchoolMember:
        '''Represents any school member.'''
        def __init__(self, name, age):
            self.name = name
            self.age = age
            print '(Initialized SchoolMember: %s)' % self.name

        def tell(self):
            '''Tell my details.'''
            print 'Name:"%s" Age:"%s"' % (self.name, self.age),

    class Teacher(SchoolMember):
        '''Represents a teacher.'''
        def __init__(self, name, age, salary):
            SchoolMember.__init__(self, name, age)
            self.salary = salary
            print '(Initialized Teacher: %s)' % self.name

        def tell(self):
            SchoolMember.tell(self)
            print 'Salary: "%d"' % self.salary

    class Student(SchoolMember):
        '''Represents a student.'''
        def __init__(self, name, age, marks):
            SchoolMember.__init__(self, name, age)
            self.marks = marks
            print '(Initialized Student: %s)' % self.name

        def tell(self):
            SchoolMember.tell(self)
            print 'Marks: "%d"' % self.marks

    t = Teacher('Mrs. Shrividya', 40, 30000)
    s = Student('Swaroop', 22, 75)

    print # prints a blank line

    members = [t, s]
    for member in members:
        member.tell() # works for both Teachers and Students

(源文件:code/inherit.py

輸出


    $ python inherit.py
    (Initialized SchoolMember: Mrs. Shrividya)
    (Initialized Teacher: Mrs. Shrividya)
    (Initialized SchoolMember: Swaroop)
    (Initialized Student: Swaroop)

    Name:"Mrs. Shrividya" Age:"40" Salary: "30000"
    Name:"Swaroop" Age:"22" Marks: "75"

它如何工作

為了使用繼承,我們把基本類的名稱作為一個(gè)元組跟在定義類時(shí)的類名稱之后。然后,我們注意到基本類的 init 方法專門使用 self 變量調(diào)用,這樣我們就可以初始化對(duì)象的基本類部分。這一點(diǎn)十分重要——Python 不會(huì)自動(dòng)調(diào)用基本類的 constructor,你得親自專門調(diào)用它。

我們還觀察到我們?cè)诜椒ㄕ{(diào)用之前加上類名稱前綴,然后把 self 變量及其他參數(shù)傳遞給它。

注意,在我們使用 SchoolMember 類的 tell 方法的時(shí)候,我們把 Teacher 和 Student 的實(shí)例僅僅作為 SchoolMember 的實(shí)例。

另外,在這個(gè)例子中,我們調(diào)用了子類型的 tell 方法,而不是 SchoolMember 類的 tell 方法。可以這樣來(lái)理解,Python 總是首先查找對(duì)應(yīng)類型的方法,在這個(gè)例子中就是如此。如果它不能在導(dǎo)出類中找到對(duì)應(yīng)的方法,它才開(kāi)始到基本類中逐個(gè)查找?;绢愂窃陬惗x的時(shí)候,在元組之中指明的。

一個(gè)術(shù)語(yǔ)的注釋——如果在繼承元組中列了一個(gè)以上的類,那么它就被稱作 多重繼承 。

概括

我們已經(jīng)研究了類和對(duì)象的多個(gè)內(nèi)容以及與它們相關(guān)的多個(gè)術(shù)語(yǔ)。通過(guò)本章,你已經(jīng)了解了面向?qū)ο蟮木幊痰膬?yōu)點(diǎn)和缺陷。Python 是一個(gè)高度面向?qū)ο蟮恼Z(yǔ)言,理解這些概念會(huì)在將來(lái)有助于你進(jìn)一步深入學(xué)習(xí) Python。

接下來(lái),我們將學(xué)習(xí)如何處理輸入/輸出已經(jīng)如何用 Python 訪問(wèn)文件。