1. 程式人生 > >面向物件的程式設計(1)——簡明python教程學習筆記

面向物件的程式設計(1)——簡明python教程學習筆記

本文大量內容來源於沈老師的簡明python教程,其中夾雜部分個人的理解如有偏頗之處還望海涵。

一.簡介

到目前為止,在我們的程式中,我們都是根據操作資料的函式或語句塊來設計程式的。這被稱為面向過程的程式設計。 還有一種把資料和功能結合起來,用稱為物件的東西包裹起來組織程式的方法。這種方法稱為面向物件的程式設計程式設計理念。在大多數時候你可以使用過程性程式設計,但是有些時候當你想要編寫大型程式或是尋求一個更加合適的解決方案的時候,你就得使用面向物件的程式設計技術。

Object-oriented programming (OOP) is a programming paradigmbased on the concept of “objects”, which may contain data, in the form of fields, often known as attributes; and code, in the form ofprocedures, often known as methods. A feature of objects is that an object’s procedures can access and often modify the data fields of the object with which they are associated (objects have a notion of “this” or “self”). In OOP, computer programs are designed by making them out of objects that interact with one another.[1][2] There is significant diversity of OOP languages, but the most popular ones are class-based, meaning that objects are instances of classes, which typically also determine their type. 面向物件程式設計(OOP)

是一種基於“物件”概念的程式設計範例,它可能包含欄位形式的資料,通常稱為屬性;以及以程式的形式存在的程式碼,通常稱為方法。 物件的一個特性是物件的過程可以訪問並經常修改與之關聯的物件的資料欄位(物件具有“this”或“self”的概念)。在OOP中,計算機程式的設計是通過彼此互動的物件來實現的。[1] [2] OOP語言有很多種,但最流行的是基於類的,這意味著物件是類的例項,通常也決定了它們的型別。 —— WIKIPEDIA

物件是面向物件程式設計的兩個主要方面。類建立一個新型別,而物件則這個類的例項 。這類似於你有一個int型別的變數,這儲存整數的變數是int類的例項(物件)。 物件可以使用普通的屬於物件的變數儲存資料。屬於一個物件或類的變數被稱為域。物件也可以使用屬於類的函式來具有功能。這樣的函式被稱為類的方法。這些術語幫助我們把它們與孤立的函式和變數區分開來。域和方法可以合稱為類的屬性。 域有兩種型別——屬於每個例項/類的物件或屬於類本身。它們分別被稱為例項變數和類變 量。 類使用class關鍵字建立。類的域和方法被列在一個縮排塊中。

二.self

類的方法與普通的函式只有一個特別的區別——它們必須有一個額外的第一個引數名稱,但是 在呼叫這個方法的時候你不為這個引數賦值,Python會提供這個值。這個特別的變數指物件本 身,按照慣例它的名稱是self。

雖然你可以給這個引數任何名稱,但是 強烈建議 你使用self這個名稱——其他名稱都是不贊成 你使用的。使用一個標準的名稱有很多優點——你的程式讀者可以迅速識別它,如果使用self 的話,還有些IDE(整合開發環境)也可以幫助你

三.類

#Filename:簡單類的建立.py

class Person:
    pass  #An empty block

p=Person()
print(p)

輸出為

<__main__.Person object at 0x03C17470>

我們使用class語句後跟類名,建立了一個新的類。這後面跟著一個縮排的語句塊形成類體。在 這個例子中,我們使用了一個空白塊,它由pass語句表示。 接下來,我們使用類名後跟一對圓括號來建立一個物件/例項。為了驗證,我們簡單地列印了這個變數的型別。它告訴我們,我們已經在main模組中有了一個Person類的例項。 可以注意到儲存物件的計算機記憶體地址也列印了出來。這個地址在你的計算機上會是另外一個 值,因為Python可以在任何空位儲存物件。

四.物件的方法

1.使用物件的方法

# 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()

輸出為

Hello,how are you?

我們看到了self的用法。注意sayHi方法沒有任何引數,但仍然在函式定義時有self。

2. __init__方法

在Python的類中有很多方法的名字有特殊的重要意義。現在我們將學習__init__方法的意義。 __init__方法在類的一個物件被建立時,馬上執行。這個方法可以用來對你的物件做一些你希 望的 初始化 。注意,這個名稱的開始和結尾都是雙下劃線。

# Filename:class_objection.py

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

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

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

輸出為

Hello,my name is DanielZhu

這裡,我們把__init__方法定義為取一個引數name(以及普通的引數self)。在這個__init__裡, 我們只是建立一個新的域,也稱為name。注意它們是兩個不同的變數,儘管它們有相同的名字,我們能夠簡單的區分它們。 最重要的是,我們沒有專門呼叫__init__方法,只是在建立一個類的新例項的時候,把引數包括在圓括號內跟在類名後面,從而傳遞給__init__方法。這是這種方法的重要之處。 現在,我們能夠在我們的方法中使用self.name域。這在sayHi方法中得到了驗證。

五.類與物件的方法

我們已經討論了類與物件的功能部分,現在我們來看一下它的資料部分。事實上,它們只是與 類和物件的名稱空間 繫結 的普通變數,即這些名稱只在這些類與物件的前提下有效。 有兩種型別的 域 ——類的變數和物件的變數,它們根據是類還是物件 擁有 這個變數而區分。 類的變數 由一個類的所有物件(例項)共享使用。只有一個類變數的拷貝,所以當某個物件 對類的變數做了改動的時候,這個改動會反映到所有其他的例項上。 物件的變數 由類的每個物件/例項擁有。因此每個物件有自己對這個域的一份拷貝,即它們不 是共享的,在同一個類的不同例項中,雖然物件的變數有相同的名稱,但是是互不相關的。一個簡單的例項可以幫助我們理解;

使用類與物件的變數

#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)

DanielZ = Person('DanielZ')
DanielZ.sayHi()
DanielZ.howMany()

DanielX = Person('DanielX')
DanielX.sayHi()
DanielX.howMany()

DanielZ.sayHi()
DanielZ.howMany()

輸出:

(Initializing DanielZ)
Hi,my name is DanielZ.
I am the only person here.
(Initializing DanielX)
Hi,my name is DanielX.
We have 2 persons here.
Hi,my name is DanielZ.
We have 2 persons here.
DanielZ says bye.
There are still 1 people left.
DanielX says bye.
I am the last one.

在該例項中:population屬於Person 類,因此是一個類的變數。name變數屬於物件(它使用self賦值)因此是物件的變數。 觀察可以發現__init__方法用一個名字來初始化Person例項。在這個方法中,我們讓population 增加1,這是因為我們增加了一個人。同樣可以發現,self.name的值根據每個物件指定,這表 明瞭它作為物件的變數的本質。 記住,你只能使用self變數來參考同一個物件的變數和方法。這被稱為 屬性參考 。 在這個程式中,我們還看到docstring對於類和方法同樣有用。我們可以在執行時使用Person. __doc__和Person.sayHi.__doc__來分別訪問類與方法的文件字串。 就如同__init__方法一樣,還有一個特殊的方法__del__,它在物件消逝的時候被呼叫。物件消 逝即物件不再被使用,它所佔用的記憶體將返回給系統作它用。在這個方法裡面,我們只是簡單 地把Person.population減1。 當物件不再被使用時,__del__方法執行,但是很難保證這個方法究竟在 什麼時候 執行。如果 你想要指明它的執行,你就得使用del語句,就如同我們在以前的例子中使用的那樣。