Python - 訪問修飾符



Python 訪問修飾符用於限制從類外部訪問類成員(即變數和方法)。訪問修飾符有三種類型:公有、受保護和私有。

  • 公有成員 - 如果可以在程式的任何地方訪問類成員,則稱該類成員為公有。

  • 受保護成員 - 可以在類內部以及派生自該類的類中訪問。

  • 私有成員 - 只能在類內部訪問。

通常,方法定義為公有的,例項變數定義為私有的。這種私有例項變數和公有方法的安排確保了封裝原則的實現。

Python 中的訪問修飾符

與 C++ 和 Java 不同,Python 不使用 Public、Protected 和 Private 關鍵字來指定訪問修飾符的型別。預設情況下,Python 類中的所有變數和方法都是公有的。

示例

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

class Employee:
   'Common base class for all employees'
   def __init__(self, name="Bhavana", age=24):
      self.name = name
      self.age = age

e1 = Employee()
e2 = Employee("Bharat", 25)

print ("Name: {}".format(e1.name))
print ("age: {}".format(e1.age))
print ("Name: {}".format(e2.name))
print ("age: {}".format(e2.age))

它將產生以下輸出 -

Name: Bhavana
age: 24
Name: Bharat
age: 25

Python 不會強制限制訪問任何例項變數或方法。但是,Python 規定了一種約定,即在變數/方法名稱前加上單下劃線或雙下劃線來模擬受保護和私有訪問修飾符的行為。

  • 要指示例項變數為私有,請在其前面加上雙下劃線(例如 "__age")。
  • 要暗示某個例項變數為受保護,請在其前面加上單下劃線(例如 "_salary")。

另一個示例

讓我們修改 Employee 類。新增另一個例項變數 salary。透過分別在前面新增雙下劃線和單下劃線,使age為私有,salary為受保護。

class Employee:
   def __init__(self, name, age, salary):
      self.name = name # public variable
      self.__age = age # private variable
      self._salary = salary # protected variable
   def displayEmployee(self):
      print ("Name : ", self.name, ", age: ", self.__age, ", salary: ", self._salary)

e1=Employee("Bhavana", 24, 10000)

print (e1.name)
print (e1._salary)
print (e1.__age)

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

Bhavana
10000
Traceback (most recent call last):
 File "C:\Users\user\example.py", line 14, in <module>
  print (e1.__age)
        ^^^^^^^^
AttributeError: 'Employee' object has no attribute '__age'

Python 顯示 AttributeError,因為 __age 是私有的,不能在類外部使用。

名稱改編

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

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

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

obj._class__privatevar

因此,要訪問 "e1" 物件的 "__age" 例項變數的值,請將其更改為 "e1._Employee__age"。

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

print (e1._Employee__age)

它現在列印 24,即e1的年齡。

Python 屬性物件

Python 的標準庫有一個內建的 property() 函式。它返回一個屬性物件。它充當 Python 類例項變數的介面。

面向物件程式設計的封裝原則要求例項變數應該具有受限的私有訪問許可權。Python 沒有為此提供有效的機制。property() 函式提供了一種替代方案。

property() 函式使用類中定義的 getter、setter 和 delete 方法為類定義屬性物件。

語法

property(fget=None, fset=None, fdel=None, doc=None)

引數

  • fget - 一個例項方法,用於檢索例項變數的值。

  • fset - 一個例項方法,用於為例項變數賦值。

  • fdel - 一個例項方法,用於刪除例項變數

  • fdoc − 屬性的文件字串。

該函式使用 getter 和 setter 方法來返回屬性物件。

Getter 和 Setter 方法

getter 方法檢索例項變數的值,通常命名為 get_varname,而 setter 方法為例項變數賦值,命名為 set_varname。

示例

讓我們在 Employee 類中定義 getter 方法 get_name() 和 get_age(),以及 setter 方法 set_name() 和 set_age()。

class Employee:
   def __init__(self, name, age):
      self.__name = name
      self.__age = age

   def get_name(self):
      return self.__name
   def get_age(self):
      return self.__age
   def set_name(self, name):
      self.__name = name
      return
   def set_age(self, age):
      self.__age=age

e1=Employee("Bhavana", 24)
print ("Name:", e1.get_name(), "age:", e1.get_age())
e1.set_name("Archana")
e1.set_age(21)
print ("Name:", e1.get_name(), "age:", e1.get_age())

它將產生以下輸出 -

Name: Bhavana age: 24
Name: Archana age: 21

getter 和 setter 方法可以檢索或為例項變數賦值。property() 函式使用它們將屬性物件新增為類屬性。

name 屬性定義如下:

name = property(get_name, set_name, "name")

類似地,您可以新增 age 屬性:

age = property(get_age, set_age, "age")

屬性物件的優勢在於,您可以使用它來檢索其關聯的例項變數的值,以及賦值。

例如:

print (e1.name) displays value of e1.__name
e1.name = "Archana" assigns value to e1.__age

示例

下面給出了包含屬性物件及其用法的完整程式:

class Employee:
   def __init__(self, name, age):
      self.__name = name
      self.__age = age

   def get_name(self):
      return self.__name
   def get_age(self):
      return self.__age
   def set_name(self, name):
      self.__name = name
      return
   def set_age(self, age):
      self.__age=age
      return
   name = property(get_name, set_name, "name")
   age = property(get_age, set_age, "age")

e1=Employee("Bhavana", 24)
print ("Name:", e1.name, "age:", e1.age)

e1.name = "Archana"
e1.age = 23
print ("Name:", e1.name, "age:", e1.age)

它將產生以下輸出 -

Name: Bhavana age: 24
Name: Archana age: 23
廣告