返回文章列表

Python物件導向程式設計核心技術

本文探討 Python 物件導向程式設計的核心概念,包含類別、物件、繼承、`self` 引數、特殊方法、方法過載與運算元過載等。文章以程式碼範例說明如何定義類別、建立物件、使用 `self`

程式設計 Python

物件導向程式設計是現代軟體開發的重要根本,Python 作為一個物件導向程式語言,提供了豐富的特性來支援物件導向的開發模式。理解self引數的應用、特殊方法的運用以及如何模擬方法和運算元過載,對於 Python 開發者來說至關重要。這些技術能夠提升程式碼的組織性、可讀性以及可維護性,同時也讓程式碼更具彈性。透過掌握這些核心技術,開發者可以更好地運用物件導向的思想來設計和構建更複雜、更強大的應用程式。

物件導向程式設計:類別、物件與繼承

深入理解 self 引數

在 Python 的物件導向程式設計中,self 是一個特殊的引數,用於參考目前的物件本身。這個引數在類別的方法定義中扮演著至關重要的角色。

self 的基本概念

當你在類別中定義一個方法時,第一個引數通常是 self。這個引數不需要在呼叫方法時傳遞,因為 Python 會自動將目前的物件例項作為 self 的值傳入方法中。

class MethodDemo:
    def Display_Message(self):
        print('歡迎來到 Python 程式設計')

ob1 = MethodDemo()
ob1.Display_Message()  # 輸出:歡迎來到 Python 程式設計

在上述範例中,Display_Message 方法沒有任何引數,但是在定義時卻有 self。這是因為 self 代表了目前的物件例項 ob1

self 與其他引數的結合使用

除了 self 之外,你還可以在方法中定義其他引數。在呼叫方法時,你只需要傳遞除了 self 之外的其他引數。

import math

class Circle:
    def Calc_Area(self, radius):
        print('半徑 = ', radius)
        return math.pi * radius ** 2

ob1 = Circle()
print('圓形面積是 ', ob1.Calc_Area(5))
# 輸出:
# 半徑 = 5
# 圓形面積是 78.53981633974483

self 與例項變數

self 不僅可以用來呼叫其他方法,還可以用來存取或修改目前物件的例項變數。如果你在方法中定義了一個與例項變數同名的區域性變數,那麼區域性變數會遮蔽例項變數。

class Prac:
    x = 5  # 例項變數

    def disp(self, x):
        x = 30  # 區域性變數
        print('區域性變數 x 的值是 ', x)
        print('例項變數 x 的值是 ', self.x)

ob = Prac()
ob.disp(50)
# 輸出:
# 區域性變數 x 的值是 30
# 例項變數 x 的值是 5

在上述範例中,使用 self.x 可以存取到例項變數 x,而直接使用 x 則是存取區域性變數。

self 與方法呼叫

你可以使用 self 在一個方法中呼叫另一個方法。

class Self_Demo:
    def Method_A(self):
        print('在 Method A 中')
        print('從 A 被呼叫了!!!')

    def Method_B(self):
        print('在 Method B 中呼叫 Method A')
        self.Method_A()  # 呼叫 Method_A

Q = Self_Demo()
Q.Method_B()
# 輸出:
# 在 Method B 中呼叫 Method A
# 在 Method A 中
# 從 A 被呼叫了!!!

顯示類別屬性和方法

你可以使用內建函式 dir() 來顯示一個類別中的所有屬性和方法。

class DisplayDemo:
    Name = ''
    Age = ''

    def read(self):
        Name = input('輸入學生姓名:')
        print('姓名 = ', Name)
        Age = input('輸入學生年齡:')
        print('年齡 = ', Age)

D1 = DisplayDemo()
D1.read()

print(dir(DisplayDemo))
# 輸出:['__class__', '__delattr__', ..., 'Age', 'Name', 'read']

物件導向程式設計:類別、物件與繼承

特殊類別屬性與存取控制

Python 中的類別具有多種特殊屬性,這些屬性提供了關於類別本身及其成員的重要資訊。瞭解這些屬性有助於更好地掌握物件導向程式設計。

特殊屬性

執行 dir() 方法或使用 __dict__ 屬性可以檢視類別的屬性和方法。

  • dir() 方法傳回一個排序後的列表,包含物件的所有屬性和方法。
  • __dict__ 屬性則傳回一個字典,包含類別的所有屬性和方法。
class DisplayDemo:
    Name = ''
    Age = ''

    def read(self):
        Name = input('Enter Name of student: ')
        print('Name = ', Name)
        Age = input('Enter Age of the Student: ')
        print('Age = ', Age)

D1 = DisplayDemo()
D1.read()

# 顯示屬性使用 __dict__
print(DisplayDemo.__dict__)

輸出結果顯示了 DisplayDemo 類別的所有屬性和方法,包括特殊方法如 __weakref____doc__

特殊屬性列表

屬性說明
C.__class__類別名稱
C.__doc__類別的檔案字串
C.__dict__類別的屬性
C.__module__類別定義所在的模組

存取控制

Python 中沒有像其他語言一樣的 publicprotectedprivate 關鍵字。所有屬性和方法預設為公開。

私有屬性與方法

Python 使用名稱改寫(name mangling)來模擬私有屬性或方法。在屬性或方法名前加上雙底線(__)即可實作。

class Person:
    def __init__(self):
        self.Name = 'Bill Gates'  # 公開屬性
        self.__BankAccNo = 10101  # 私有屬性

    def Display(self):
        print('Name = ', self.Name)
        print('Bank Account Number = ', self.__BankAccNo)

P = Person()
print('Name = ', P.Name)
P.Display()

# 嘗試存取私有變數將失敗
try:
    print('Salary = ', P.__BankAccNo)
except AttributeError as e:
    print(e)

輸出結果表明嘗試存取私有屬性 __BankAccNo 將引發 AttributeError

__init__ 方法(建構子)

__init__ 方法是一種特殊方法,用於初始化物件的例項變數。當建立類別的例項時,__init__ 方法會自動執行。

使用 __init__ 方法初始化屬性

class Circle:
    def __init__(self, pi):
        self.pi = pi

    def calc_area(self, radius):
        return self.pi * radius ** 2

C1 = Circle(3.14)
print('The area of Circle is ', C1.calc_area(5))

輸出結果正確計算了圓的面積。

初始化屬性值

class Circle:
    pi = 0
    radius = 0

    def __init__(self):
        self.pi = 3.14
        self.radius = 5

    def calc_area(self):
        print('Radius = ', self.radius)
        return self.pi * self.radius ** 2

C1 = Circle()
print('The area of Circle is ', C1.calc_area())

輸出結果顯示了使用 __init__ 方法初始化屬性值的效果。

物件導向程式設計:類別、物件與繼承

物件導向程式設計是Python中一個非常重要的概念,它允許開發者建立可重複使用且模組化的程式碼。在本章中,我們將探討類別、物件、繼承等核心概念,並透過例項演示如何使用這些概念來解決實際問題。

類別與物件的基本概念

在Python中,類別是一種自定義的資料型別,它定義了物件的屬性和方法。物件是類別的例項,每個物件都有自己的屬性值。

程式 10.16:計算盒子的體積

class Box:
    def __init__(self):
        self.width = 5
        self.height = 5
        self.depth = 5

    def calc_vol(self):
        print('寬度 = ', self.width)
        print('高度 = ', self.height)
        print('深度 = ', self.depth)
        return self.width * self.height * self.depth

B1 = Box()
print('立方體的體積是 ', B1.calc_vol())

內容解密:

  1. __init__ 方法:這是一個特殊的方法,當物件被建立時自動呼叫,用於初始化物件的屬性。
  2. self 引數:代表目前物件的例項,用於存取和修改物件的屬性。
  3. calc_vol 方法:計算並傳回盒子的體積,同時列印預出盒子的尺寸。

輸出結果:

寬度 =  5
高度 =  5
深度 =  5
立方體的體積是  125

將物件作為引數傳遞給方法

Python允許將物件作為引數傳遞給方法,這使得物件之間的互動變得更加靈活。

程式 10.17:比較兩個物件是否相等

class Test:
    def __init__(self, x, y):
        self.a = x
        self.b = y

    def equals(self, obj):
        if obj.a == self.a and obj.b == self.b:
            return True
        else:
            return False

Obj1 = Test(10, 20)
Obj2 = Test(10, 20)
Obj3 = Test(12, 90)
print('Obj1 == Obj2 ', Obj1.equals(Obj2))
print('Obj1 == Obj3 ', Obj1.equals(Obj3))

內容解密:

  1. equals 方法:比較目前物件與傳入的物件是否具有相同的屬性值。
  2. 物件比較邏輯:透過比較兩個物件的 ab 屬性是否相等來判斷它們是否相同。

輸出結果:

Obj1 == Obj2  True
Obj1 == Obj3  False

解構函式(__del__ 方法)

解構函式在物件被銷毀前呼叫,用於釋放資源或執行清理操作。

程式 10.19:演示解構函式的使用

class Destructor_Demo:
    def __init__(self):
        print('歡迎')

    def __del__(self):
        print('解構函式執行成功')

Ob1 = Destructor_Demo()
Ob2 = Ob1
Ob3 = Ob1
print('Ob1 的 ID = ', id(Ob1))
print('Ob2 的 ID = ', id(Ob2))
print('Ob3 的 ID = ', id(Ob3))
del Ob2
del Ob1
del Ob3

內容解密:

  1. __del__ 方法:當物件的所有參照都被刪除時,Python會呼叫解構函式。
  2. id() 函式:傳回物件的唯一識別符,用於確認多個變數是否參照同一個物件。

輸出結果:

歡迎
Ob1 的 ID =  某個ID
Ob2 的 ID =  同上ID
Ob3 的 ID =  同上ID
解構函式執行成功

類別成員測試

使用 isinstance() 函式可以檢查一個物件是否屬於某個類別。

程式 10.20:演示 isinstance() 的使用

class A:
    pass

class B:
    pass

Ob1 = A()
Ob2 = B()

print(isinstance(Ob1, A))  # True
print(isinstance(Ob1, B))  # False
print(isinstance(Ob2, B))  # True

內容解密:

  1. isinstance() 函式:檢查第一個引數是否是第二個引數(類別)的例項。
  2. 型別檢查:用於確定物件的型別,方便進行相應的操作。

方法過載

雖然Python不直接支援像其他語言那樣的方法過載,但可以透過預設引數或可變引數列表來模擬類別似行為。

示例:模擬方法過載

class OverloadDemo:
    def add(self, *args):
        return sum(args)

P = OverloadDemo()
print(P.add(10, 20))       # 30
print(P.add(10, 20, 30))   # 60

內容解密:

  1. 可變引數列表 (*args):允許方法接受任意數量的引數。
  2. sum() 函式:計算所有傳入引數的總和。

本章介紹了Python中物件導向程式設計的核心概念,包括類別、物件、繼承以及相關的特殊方法。透過這些知識,可以編寫出更加模組化和可重用的程式碼。接下來的章節將進一步探討更多進階主題。

Python 中的方法過載與運算元過載

在 Python 程式設計中,方法過載(Method Overloading)與運算元過載(Operator Overloading)是兩個重要的概念,它們能夠提升程式碼的可讀性與靈活性。

方法過載(Method Overloading)

方法過載是一種允許開發者定義多個具有相同名稱但不同引數的方法的技術。然而,Python 並不直接支援像 C++ 或 Java 那樣的方法過載。Python 的方法過載可以透過使用可變引數或預設引數來實作。

程式範例:使用 isinstanceof 實作方法過載

class Demo:
    def __init__(self):
        self.result = 0

    def add(self, instanceOf=None, *args):
        if instanceOf == 'int':
            self.result = 0
            for i in args:
                self.result += i
        elif instanceOf == 'str':
            self.result = ''
            for i in args:
                self.result += i
        return self.result

D1 = Demo()
print(D1.add('int', 10, 20, 30))
print(D1.add('str', ' I ', ' Love ', ' Python ', ' Programming '))

內容解密:

  1. Demo 類別中的 add 方法接受一個 instanceOf 引數和可變數量的引數 *args
  2. 根據 instanceOf 的值,方法會對 args 中的元素進行不同的操作:如果 instanceOf'int',則進行加法運算;如果是 'str',則進行字串連線。
  3. 該實作展示瞭如何在 Python 中模擬方法過載。

運算元過載(Operator Overloading)

運算元過載允許開發者為自定義的資料型別定義運算元的行為,使得這些資料型別能夠像內建型別一樣自然地進行運算。

特殊方法(Special Methods)

Python 將運算元與特殊方法相關聯。例如,+ 運算元對應於 __add__ 方法。

程式範例:過載 + 運算元

class OprOverloadingDemo:
    def __init__(self, X):
        self.X = X

    def __add__(self, other):
        print('The value of Ob1 =', self.X)
        print('The value of Ob2 =', other.X)
        print('The Addition of two objects is:', end='')
        return self.X + other.X

Ob1 = OprOverloadingDemo(20)
Ob2 = OprOverloadingDemo(30)
print(Ob1 + Ob2)

內容解密:

  1. OprOverloadingDemo 類別定義了一個 __add__ 方法,用於過載 + 運算元。
  2. 當對兩個 OprOverloadingDemo 物件使用 + 運算元時,Python 會呼叫 __add__ 方法,將兩個物件的 X 屬性相加。
  3. 該實作展示瞭如何透過運算元過載使自定義物件支援自然的運算。