Python 简明教程

Python - Access Modifiers

Python access modifiers 用于限制对类中成员(即变量和方法)的访问。有三种类型的访问修饰符,即 public、protected 和 private。

The Python access modifiers are used to restrict access to class members (i.e., variables and methods) from outside the class. There are three types of access modifiers namely public, protected, and private.

  1. Public members − A class member is said to be public if it can be accessed from anywhere in the program.

  2. Protected members − They are accessible from within the class as well as by classes derived from that class.

  3. Private members − They can be accessed from within the class only.

通常,方法被定义为公有方法,而实例变量则为私有变量。私有实例变量和公有方法的这种安排确保了封装原则的实施。

Usually, methods are defined as public and instance variable are private. This arrangement of private instance variables and public methods ensures implementation of principle of encapsulation.

Access Modifiers in Python

与 C++ 和 Java 不同,Python 不使用 Public、Protected 和 Private 关键字来指定访问修饰符的类型。默认情况下,Python 类中的所有变量和方法都是公有的。

Unlike C++ and Java, Python does not use the Public, Protected and Private keywords to specify the type of access modifiers. By default, all the variables and methods in a Python class are public.

Example

在这里,我们有 Employee 类,其实例变量为 name 和 age。此类的对象具有这两个属性。它们可以从类的外部直接访问,因为它们是公共的。

Here, we have Employee class with instance variables name and age. An object of this class has these two attributes. They can be directly accessed from outside the class, because they are public.

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))

它将生成以下 output

It will produce the following output

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

Python 不会强制限制访问任何实例变量或方法。然而,Python 规定了一个惯例,用单下划线或双下划线作为变量/方法名称的前缀,以模拟受保护和私有访问修饰符的行为。

Python doesn’t enforce restrictions on accessing any instance variable or method. However, Python prescribes a convention of prefixing name of variable/method with single or double underscore to emulate behavior of protected and private access modifiers.

  1. To indicate that an instance variable is private, prefix it with double underscore (such as "__age").

  2. To imply that a certain instance variable is protected, prefix it with single underscore (such as "_salary").

Another Example

让我们修改 Employee 类。添加另一个实例变量 salary。通过分别加上双下划线和单下划线前缀将 age 设置为私有的,将 salary 设置为受保护的。

Let us modify the Employee class. Add another instance variable salary. Make age private and salary as protected by prefixing double and single underscores respectively.

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)

当您运行此代码时,它将生成以下 output

When you run this code, it will produce the following output

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 displays AttributeError because __age is private, and not available for use outside the class.

Name Mangling

Python 不会阻止对私有数据的访问,它仅仅留给程序员的智慧,不会编写任何可以从类外访问它的代码。您仍然可以通过 Python 的名称混淆技术访问私有成员。

Python doesn’t block access to private data, it just leaves for the wisdom of the programmer, not to write any code that access it from outside the class. You can still access the private members by Python’s name mangling technique.

名称混淆是将双下划线成员的名称更改为 object._class__variable 格式的过程。如果需要,仍然可以从类外访问它,但应该避免此做法。

Name mangling is the process of changing name of a member with double underscore to the form object._class__variable. If so required, it can still be accessed from outside the class, but the practice should be refrained.

在我们的示例中,私有实例变量 "__name" 混淆后变为 −

In our example, the private instance variable "__name" is mangled by changing it to the format −

obj._class__privatevar

因此,要获取 "e1" 对象的 "_age" 实例变量值,请将其更改为 "e1._Employee_age"。

So, to access the value of "_age" instance variable of "e1" object, change it to "e1._Employee_age".

将上面程序中的 print() 语句更改为 −

Change the print() statement in the above program to −

print (e1._Employee__age)

它现在打印 24,即 e1 的年龄。

It now prints 24, the age of e1.

Python Property Object

Python 的标准库有一个内置的 property() 函数。它返回一个属性对象。它充当 Python 类的实例变量的接口。

Python’s standard library has a built-in property() function. It returns a property object. It acts as an interface to the instance variables of a Python class.

面向对象编程的封装原则要求实例变量具有受限制的私有访问。Python 没有高效的机制用于此目的。property() 函数提供了一个替代方案。

The encapsulation principle of object-oriented programming requires that the instance variables should have a restricted private access. Python doesn’t have efficient mechanism for the purpose. The property() function provides an alternative.

property() 函数使用在类中定义的 getter、setter 和 delete 方法来为类定义一个属性对象。

The property() function uses the getter, setter and delete methods defined in a class to define a property object for the class.

Syntax

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

Parameters

  1. fget − an instance method that retrieves value of an instance variable.

  2. fset − an instance method that assigns value to an instance variable.

  3. fdel − an instance method that removes an instance variable

  4. fdoc − Documentation string for the property.

该函数使用 getter 和 setter 方法以返回属性对象。

The function uses getter and setter methods to return the property object.

Getters and Setter Methods

getter 方法获取一个实例变量的值,通常命名为 get_varname,而 setter 方法给这个变量赋值,命名为 set_varname。

A getter method retrieves the value of an instance variable, usually named as get_varname, whereas the setter method assigns value to an instance variable − named as set_varname.

Example

让我们给 Employee 类中定义 getter 方法 get_name() 和 get_age(),以及 setter 方法 set_name() 和 set_age()。

Let us define getter methods get_name() and get_age(), and setters set_name() and set_age() in the Employee class.

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())

它将生成以下 output

It will produce the following output

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

getter 和 setter 方法可以获取或给实例变量赋值。property() 函数利用它们添加属性对象作为类属性。

The getter and setter methods can retrieve or assign value to instance variables. The property() function uses them to add property objects as class attributes.

name 属性的定义如下 −

The name property is defined as −

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

类似地,你可以添加 age 属性 −

Similarly, you can add the age property −

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

属性对象的一个优势是你可以利用它来检索其关联的实例变量的值以及指定值。

The advantage of the property object is that you can use to retrieve the value of its associated instance variable, as well as assign value.

例如,

For example,

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

Example

包含属性对象及用法的完整程序如下 −

The complete program with property objects and their use is given below −

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)

它将生成以下 output

It will produce the following output

Name: Bhavana age: 24
Name: Archana age: 23