Python - 面向物件概念



OOP 是一個縮寫,代表面向物件程式設計正規化。它被定義為一種程式設計模型,使用物件的概念,物件指的是具有狀態和行為的現實世界實體。本章幫助您成為 Python 語言中使用面向物件程式設計支援的專家。

Python 是一種支援面向物件程式設計的程式語言。這使得建立和使用類和物件變得簡單。如果您之前沒有面向物件程式設計的經驗,那麼您來對地方了。讓我們從討論面向物件程式設計 (OOP) 的一個小介紹開始,以幫助您。

過程式方法

20 世紀 50 年代和 60 年代開發的早期程式語言被認為是過程式(或面向過程)語言。

計算機程式透過按邏輯順序編寫一系列指令來描述執行特定任務的過程。更復雜程式的邏輯被分解成更小但獨立且可重用的語句塊,稱為函式。

每個函式都以這樣一種方式編寫,即它可以與程式中的其他函式互動。屬於一個函式的資料可以輕鬆地以引數的形式與其他函式共享,並且被呼叫的函式可以將其結果返回給呼叫函式。

與過程式方法相關的主要問題如下:-

  • 其自頂向下的方法使程式難以維護。

  • 它使用了大量的全域性資料項,這是不希望的。過多的全域性資料項會增加記憶體開銷。

  • 它更重視過程,而沒有將資料視為同等重要,並將其視為理所當然,從而使其在程式中自由移動。

  • 資料在函式之間不受限制地移動。在現實生活中,期望函式與其要處理的資料之間存在明確的關聯。

Python - 面向物件概念

在現實世界中,我們處理和處理物件,例如學生、員工、發票、汽車等。物件不僅是資料,也不僅是函式,而是兩者的組合。每個現實世界的物件都與其相關的屬性和行為。

oop_concepts

屬性

  • 學生的姓名、班級、科目、分數等

  • 員工的姓名、職位、部門、薪水等

  • 發票號碼、客戶、產品程式碼和名稱、價格和數量等,在一個發票中

  • 汽車的註冊號、車主、公司、品牌、馬力、速度等

每個屬性都將有一個與其關聯的值。屬性等同於資料。

行為

處理與物件關聯的屬性。

  • 計算學生的平均成績

  • 計算應付給員工的獎金

  • 對發票金額徵收 GST

  • 測量汽車的速度

行為等同於函式。在現實生活中,屬性和行為不是相互獨立的,而是共存的。

面向物件方法最重要的特徵是將屬性及其功能定義為一個稱為類的單元。它作為所有具有相似屬性和行為的物件的藍圖。

在 OOP 中,類定義了其物件具有的屬性,以及其行為。另一方面,物件是類的例項。

OOPs 概念的原則

面向物件程式設計正規化以以下原則為特徵:-

  • 物件

  • 封裝

  • 繼承

  • 多型

principles_of_oop

類 & 物件

類(class)是使用者自定義的物件原型,它定義了一組屬性來描述該類任何物件的特徵。這些屬性包括資料成員(類變數和例項變數)和方法,可以透過點運算子訪問。

物件(object)指的是某個類的例項。例如,名為 obj 且屬於類 Circle 的物件就是該類的例項。它是根據其類定義的資料結構的唯一例項。物件包含資料成員(類變數和例項變數)和方法。

示例

以下示例演示瞭如何在 Python 中建立類及其物件。

# defining class
class Smartphone:
   # constructor    
   def __init__(self, device, brand):
      self.device = device
      self.brand = brand
   
   # method of the class
   def description(self):
      return f"{self.device} of {self.brand} supports Android 14"

# creating object of the class
phoneObj = Smartphone("Smartphone", "Samsung")
print(phoneObj.description()) 

執行上述程式碼後,將顯示以下輸出:

Smartphone of Samsung supports Android 14

封裝

類的成員資料只能供類內部定義的函式處理。另一方面,類的函式可以從類上下文外部訪問。因此,物件資料對類外部的環境是隱藏的。類函式(也稱為方法)封裝了物件資料,以防止對其進行未經授權的訪問。

示例

在這個例子中,我們使用封裝的概念來設定桌面的價格。

class Desktop:
   def __init__(self):
      self.__max_price = 25000

   def sell(self):
      return f"Selling Price: {self.__max_price}"

   def set_max_price(self, price):
      if price > self.__max_price:
         self.__max_price = price

# Object
desktopObj = Desktop()
print(desktopObj.sell()) 

# modifying the price directly
desktopObj.__max_price = 35000
print(desktopObj.sell()) 

# modifying the price using setter function
desktopObj.set_max_price(35000)
print(desktopObj.sell())        

執行上述程式碼後,將產生以下結果:

Selling Price: 25000
Selling Price: 25000
Selling Price: 35000

繼承

面向物件程式設計(OOP)的軟體建模方法能夠擴充套件現有類的功能來構建新類,而不是從頭開始構建。在 OOP 術語中,現有類稱為 基類或父類,而新類稱為 子類或派生類

子類繼承父類的資料定義和方法。這有助於重用已有的功能。子類可以新增一些新的定義或重新定義基類函式。

語法

派生類的宣告方式與父類非常相似;但是,在類名之後需要提供要繼承的基類列表:

class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Optional class documentation string'
   class_suite

示例

以下示例演示了 Python 中繼承的概念:

#!/usr/bin/python
# define parent class
class Parent:        
   parentAttr = 100
   def __init__(self):
      print ("Calling parent constructor")

   def parentMethod(self):
      print ("Calling parent method")

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print ("Parent attribute :", Parent.parentAttr)

# define child class
class Child(Parent): 
   def __init__(self):
      print ("Calling child constructor")

   def childMethod(self):
      print ("Calling child method")

# instance of child
c = Child()  
# child calls its method        
c.childMethod() 
# calls parent's method     
c.parentMethod()  
# again call parent's method   
c.setAttr(200)  
# again call parent's method     
c.getAttr()          

執行上述程式碼後,將產生以下結果:

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

同樣,您可以從多個父類派生一個類,如下所示:

class A:        # define your class A
.....

class B:         # define your class B
.....

class C(A, B):   # subclass of A and B
.....

您可以使用 issubclass() 或 isinstance() 函式來檢查兩個類和例項之間的關係。

  • issubclass(sub, sup) 布林函式在給定的子類 sub 確實是超類 sup 的子類時返回 True。

  • isinstance(obj, Class) 布林函式在 obj 是類 Class 的例項或類 Class 的子類的例項時返回 True。

多型

多型性(Polymorphism)是一個希臘詞,意思是具有多種形式。在 OOP 中,當每個子類都提供了自己在基類中抽象方法的實現時,就會發生多型性。

您可以隨時覆蓋父類的方法。覆蓋父類方法的一個原因是您可能希望在子類中實現特殊或不同的功能。

示例

在這個例子中,我們覆蓋了父類的方法。

# define parent class
class Parent:        
   def myMethod(self):
      print ("Calling parent method")

# define child class
class Child(Parent): 
   def myMethod(self):
      print ("Calling child method")

# instance of child
c = Child()
# child calls overridden method          
c.myMethod()         

執行上述程式碼後,將產生以下結果:

Calling child method

Python 中的基類過載方法

下表列出了一些您可以在自己的類中覆蓋的一些通用功能:

序號 方法、描述和示例呼叫
1

__init__ ( self [,args...] )

建構函式(帶任何可選引數)

示例呼叫:obj = className(args)

2

__del__( self )

解構函式,刪除物件

示例呼叫:del obj

3

__repr__( self )

可計算的字串表示形式

示例呼叫:repr(obj)

4

__str__( self )

可列印的字串表示形式

示例呼叫:str(obj)

5

__cmp__ ( self, x )

物件比較

示例呼叫:cmp(obj, x)

Python 中的運算子過載

假設您建立了一個 Vector 類來表示二維向量,當您使用加號運算子來新增它們時會發生什麼?很可能 Python 會報錯。

但是,您可以在類中定義 __add__ 方法來執行向量加法,然後加號運算子將按預期工作:

示例

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)

執行上述程式碼後,將產生以下結果:

Vector(7,8)
廣告