私有属性和受保护属性

C ++和Java之类的经典面向对象语言通过公有(public)、私有(private)和受保护(protected)的关键字来控制对类资源的访问。类的私有成员拒绝从类外部环境访问。它们只能在类的内部处理。

可从类外部访问公有成员(通常是在类中声明的方法)。调用公有方法需要相同类的对象。私有实例变量和公共方法的这种安排确保了数据封装的原理。

类的受保护成员可以从该类内部访问,也可以用于其子类。不允许其他环境访问它。这样可以使子类继承父类的特定资源。

Python没有有效限制访问任何实例变量或方法的机制。 Python规定了在变量/方法名称前加单下划线双下划线的约定,以模拟受保护和私有访问说明符的行为。

默认情况下,Python类中的所有成员都是公有的。可以从类环境之外访问任何成员。

Example: Public Attributes

class Employee:
    def __init__(self, name, sal):
        self.name=name
        self.salary=sal

可以访问员工类的属性,也可以修改其值,如下所示。

e1=Employee("Kiran",10000)
e1.salary
10000
e1.salary=20000
e1.salary
20000

Python的实例变量受保护的约定是在其上添加前缀_(单个下划线)。 这将约定防止对其进行访问, 除非访问来自子类。

Example: Protected Attributes

class Employee:
    def __init__(self, name, sal):
        self._name=name  # protected attribute 
        self._salary=sal # protected attribute

实际上,这不会阻止实例变量访问或修改实例。 仍然可以执行以下操作:

e1=Employee("Swati", 10000)
e1._salary
10000
e1._salary=20000
e1._salary
20000

因此,负责的程序员应避免从其类的外部访问和修改以_开头的实例变量。

同样,在变量前加上双下划线__使其变为私有。 强烈建议不要在类外碰它。 尝试这样做会导致AttributeError:

Example: Private Attributes

class Employee:
    def __init__(self, name, sal):
        self.__name=name  # private attribute 
        self.__salary=sal # private attribute
e1=Employee("Bill",10000)
e1.__salary
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-9-d5a2eb37a52c> in <module>
      1 e1=Employee("Bill",10000)
----> 2 e1.__salary


AttributeError: 'Employee' object has no attribute '__salary'

Python执行私有变量的改名处理(name mangling)。 每个具有双下划线的成员将更改为_object._class__variable。 如果需要,仍然可以从类外部访问它,但是应该避免这种做法。

e1=Employee("Bill",10000)
e1._Employee__salary
10000
e1._Employee__salary=20000
e1._Employee__salary
20000