Python - 封裝



封裝是將屬性和方法捆綁到一個單元中的過程。它是面向物件程式設計正規化所基於的主要支柱之一。

我們知道類是物件的自定義原型。它定義了一組資料成員和方法,能夠處理資料。

根據資料封裝原則,描述物件的那些資料成員對類外部的環境是隱藏的。它們只能透過同一類中的方法訪問。另一方面,方法本身可以從類上下文外部訪問。因此,物件資料被方法封裝。這樣,封裝可以防止直接訪問物件資料。

在 Python 中實現封裝

C++Java這樣的語言使用訪問修飾符來限制對類成員(即變數和方法)的訪問。這些語言有關鍵字 public、protected 和 private 來指定訪問型別。

如果類成員可以在程式的任何地方訪問,則稱其為public。僅允許在類內部訪問私有成員。通常,方法被定義為 public,例項變數被定義為 private。這種 private 例項變數和 public 方法的安排確保了封裝的實現。

與這些語言不同,Python沒有規定類成員可以具有的訪問型別。預設情況下,Python 類中的所有變數和方法都是 public,如下例所示。

示例 1

這裡,我們有一個 Employee 類,它包含例項變數 **name** 和 **age**。這個類的物件具有這兩個屬性。因為它們是公開的,所以可以直接從類外部訪問。

class Student:
   def __init__(self, name="Rajaram", marks=50):
      self.name = name
      self.marks = marks

s1 = Student()
s2 = Student("Bharat", 25)

print ("Name: {} marks: {}".format(s1.name, s2.marks))
print ("Name: {} marks: {}".format(s2.name, s2.marks))

它將產生以下輸出 -

Name: Rajaram marks: 50
Name: Bharat marks: 25

在上面的例子中,例項變數是在類內部初始化的。但是,沒有限制從類外部訪問例項變數的值,這違反了封裝的原則。

雖然沒有關鍵字來強制可見性,但 Python 有一種用特殊方式命名例項變數的約定。在 Python 中,在變數/方法名稱前加一個或兩個下劃線來模擬受保護和私有訪問修飾符的行為。

如果變數名字首為兩個下劃線(例如“**__age**”),則該例項變數是私有的,類似地,如果變數名字首為一個下劃線(例如“**_salary**”)。

示例 2

讓我們修改 Student 類。新增另一個例項變數 salary。將 name 設定為私有,並將 **marks** 設定為私有,方法是在它們前面加上雙下劃線。

class Student:

   def __init__(self, name="Rajaram", marks=50):
      self.__name = name
      self.__marks = marks
   def studentdata(self):
      print ("Name: {} marks: {}".format(self.__name, self.__marks))
      
s1 = Student()
s2 = Student("Bharat", 25)

s1.studentdata()
s2.studentdata()
print ("Name: {} marks: {}".format(s1.__name, s2.__marks))
print ("Name: {} marks: {}".format(s2.__name, __s2.marks))

執行此程式碼時,它將產生以下輸出 -

Name: Rajaram marks: 50
Name: Bharat marks: 25
Traceback (most recent call last):
 File "C:\Python311\hello.py", line 14, in <module>
  print ("Name: {} marks: {}".format(s1.__name, s2.__marks))
AttributeError: 'Student' object has no attribute '__name'

上面的輸出清楚地表明,例項變數 name 和 age 可以被類內部宣告的方法(studentdata() 方法)訪問,但是雙下劃線字首使變數成為私有的,因此,從類外部訪問它們是被限制的,這會引發 AttributeError 錯誤。

什麼是名稱改編(Name Mangling)?

Python 並沒有完全阻止對私有資料的訪問。它只是將其留給程式設計師的智慧,不要編寫任何從類外部訪問它的程式碼。您仍然可以透過 Python 的名稱改編技術訪問私有成員。

名稱改編是將帶有雙下劃線的成員名稱更改為 object._class__variable 格式的過程。如果需要,它仍然可以從類外部訪問,但應避免這種做法。

在我們的例子中,私有例項變數 "__name" 透過將其更改為以下格式來進行改編

obj._class__privatevar

因此,要訪問 "s1" 物件的 "__marks" 例項變數的值,將其更改為 "s1._Student__marks"。

將上面程式中的 print() 語句更改為 -

print (s1._Student__marks)

它現在列印 50,即 s1 的分數。

因此,我們可以得出結論,Python 並沒有完全按照面向物件程式設計的理論實現封裝。它採用了一種更成熟的方法來處理它,透過規定一個命名約定,並允許程式設計師在確實需要在公共範圍內訪問私有資料時使用名稱改編。

廣告