外观
Python 缺少真正的 OOP 封装
True OOP Encapsulation is Missing From Python
使用访问修饰符(public、protected 和 private)是 OOP 中封装(encapsulation)的基础。

这不仅是 Python 的问题,也适用于一般的 OOP。然而,当我们具体谈论 Python 时,会发现它没能提供真正的封装机制,而封装正是人们在 OOP 代码中想要利用的特性。怎么回事呢?我们就在本章中搞清楚。你可能已经知道,OOP 中类的属性可以分为三类:
- 公有成员(public)在基类内外都可以被访问,并且会被所有子类继承。
- 受保护成员(protected)在基类和子类中都可以被访问,但在类外部不可访问。
- 私有成员(private)只能在基类内部被访问。
但是,在 Python 中并没有这样严格的强制。这与 C++ 等许多其他编程语言不同。因此,受保护成员的行为与公有成员完全一样。更有甚者,私有成员也可以(以某种方式)在类外部被访问到。
为了更清楚地说明,来看下面这个类的实现:

从语法上讲,在 Python 中:
- 公有成员用 0 个前导下划线声明。
- 受保护成员用 1 个前导下划线声明。
- 私有成员用 2 个前导下划线声明。
接下来,我们实例化一个类对象:

继续,正如人们所预期的,公有属性可以在类外部被访问:

然而,受保护属性同样也能在类外部被访问,而理想情况下这本不应该发生:

最后,在声明私有成员时,Python 会执行名称改写(name mangling)。这是一种编程中用来避免不同类之间命名冲突的技术。Python 通过给所有带两个前导下划线的成员附加下划线前缀的类名(_Class)来进行名称改写。

因此,尽管私有成员无法用其原始名字直接访问,但仍然可以用名称改写后得到的那个名字来访问它。
这一点在下面得到了演示:

正如上述所有示例所展示的那样,受保护成员和私有成员(借助名称改写)都能像公有成员一样被访问。因此,每一位使用 OOP 的 Python 程序员都必须记住:Python 从来不会强制执行封装。相反,在 Python 中利用封装机制主要依靠约定。这些约定用来向其他程序员传达类成员的可访问性规则。

因此,遵守这些约定是程序员自己的责任。