天天看點

Day08 - 面向對象程式設計基礎

日期:2021年1月25日

今天是學習Python的第八天,到面向對象了,相較于昨天,今天的内容合理多了,學起來也快一些。

學習用的教材是GitHub上駱昊編寫的《Python - 100天從新手到大師》

所有編寫的源代碼均放在GitHub上:https://github.com/svip886/Python_learning

一、類和對象

簡單的說,類是對象的藍圖和模闆,而對象是類的執行個體。類是抽象的概念,而對象是具體的東西。在面向對象程式設計的世界中,一切皆為對象,對象都有屬性和行為,每個對象都是獨一無二的,而且對象一定屬于某個類(型)。當我們把一大堆擁有共同特征的對象的靜态特征(屬性)和動态特征(行為)都抽取出來後,就可以定義出一個叫做“類”的東西。

二、類的定義和對象的使用

Python和C++一樣,使用關鍵字

class

來定義類,下面是建立類的示例

定義一個矩形Rect類,并寫出計算周長和面積的成員函數:

class Rect:
    # __init__是一個特殊方法用于在建立對象時進行初始化,就像C++中的構造函數
    def __init__(self,l,w): # 為Rect對象綁定長度l,寬度w
        self.l=l
        self.w=w

    def circumference(self):
        print('矩形周長為',2*self.l*self.w)

    def area(self):
        print('矩形面積為',self.l*self.w)

def main():
    # 建立Rect對象并賦予長和寬
    s=Rect(3,2)
    # 調用計算長度和寬度的成員函數
    s.circumference()
    s.area()

if __name__=='__main__':
    main()
           

二、通路可見性問題

Python和C++不同,對象的方法通常都是公開的(pubilc),如果希望屬性是私有的(private),可以在屬性命名是用兩個下劃線

"__"

作為開頭,使其隐藏,但仍可以通過

_類名__成員

來通路它,等于加了一層保護。

同樣的例子,稍作修改

class Rect:

    def __init__(self,l,w):
        self.l=l # 将屬性設為私有
        self.__w=w

    def circumference(self):
        print('矩形周長為',2*self.l*self.__w)

    def __area(self):
        print('矩形面積為',self.l*self.__w)

def main():
    s=Rect(3,2)
    s.circumference() # 矩形周長為12
    s.__area() # AttributeError: 'Rect' object has no attribute '__area'
    s._Rect__area() # 矩形面積為6
    print(s.l) # 3
    print(s.__w) # AttributeError: 'Rect' object has no attribute '__w'
    print(s._Rect__w) # 2

if __name__=='__main__':
    main()
           

💡 實際開發中,不建議将屬性設為私有,這會導緻子類無法通路。是以一個好的習慣是,讓屬性名以單下劃線開頭來表示屬性是受保護的,更多的是像一種暗喻,提醒自己本類外使用需要慎重。

三、練習

  1. 定義一個類描述數字時鐘
    from time import sleep
    from os import system
    class Clock:
        def __init__(self,hour=0,minute=0,second=0):
            self._hour=hour
            self._minute=minute
            self._second=second
    
        def run(self):
            self._second+=1
            if self._second==60:
                self._second=0
                self._minute+=1
                if self._minute==60:
                    self._minute=0
                    self._hour+=1
                    if self._hour==24:
                        self._hour=0
    
        def output(self):
            while 1:
                self.run()
                system('cls')
                print('目前時間:%02d:%02d:%02d' % (self._hour,self._minute,self._second))
                sleep(1)
    
    def main():
        s=Clock(13,12,55)
        s.output()
    
    if __name__=='__main__':
        main()
               
    💡 結合了之前的跑馬燈練習學來的

    os.system()

    函數,實作了指令行的時間重新整理。
  2. 定義一個類描述平面上的點并提供移動點和計算到另一個點距離的方法
    class Point:
        def __init__(self,x=0,y=0):
            self._x=x
            self._y=y
    
        def output(self):
            print('目前點的坐标為(%d,%d)' % (self._x,self._y))
    
        def move(self):
            self._x=int(input('x='))
            self._y=int(input('y='))
    
        def distance(self,a):
            d=((self._y-a._y)**2+(self._x-a._x)**2)**0.5
            print('兩點之間的距離為:%.2f' % (d))
    
    def main():
        p1=Point(2,4)
        p2=Point(3,3)
        p1.output()
        p2.output()
        p1.move()
        p1.output()
        p1.distance(p2)
    
    if __name__=='__main__':
        main()