13.14 私有化

默认情况下,属性在Python中都是“公开的”,类所在模块和导入了类所在模块的其他模块的代码都可以访问到。很多00语言给数据加上一些可见性,只提供访问函数来访问其值。这就是熟知的实现隐藏,是对象封装中的一个关键部分。

大多数面向对象语言提供“访问控制符”来限定成员函数的访问。

1.双下划线(__)

Python为类元素(属性和方法)的私有性提供初步的形式。由双下划线开始的属性在运行时被“混淆”,所以直接访问是不允许的。实际上,会在名字前面加上下划线和类名。比如,以例13.6(numstr.py)中的self.num属性为例,被“混淆”后,用于访问这个数据值的标识就变成了self.NumStr__num。把类名加上后形成的新的“混淆”结果将可以防止在祖先类或子孙类中的同名冲突。

尽管这样做提供了某种层次上的私有化,但算法处于公共域中并且很容易被“击败”。这更多的是一种对导入源代码无法获得的模块或对同一模块中的其他代码的保护机制。

这种名字混淆的另一个目的,是为了保护XXX变量不与父类名字空间相冲突。如果在类中有一个XXX属性,它将不会被其子类中的XXX属性覆盖。(回忆一下,如果父类仅有一个XXX属性,子类也定义了这个,这时,子类的XXX就是覆盖了父类的XXX,这就是为什么你必须使用PARENT.XXX来调用父类的同名方法。)使用XXX,子类的代码就可以安全地使用XX,而不必担心它会影响到父类中的XXX。

2.单下划线(_)

与我们在第12章发现的那样,简单的模块级私有化只需要在属性名前使用一个单下划线字符。这就防止模块的属性用“from mymodule import*”来加载。这是严格基于作用域的,所以这同样适合于函数。

在Python2.2中引进的新式类,增加了一套全新的特征,让程序员在类及实例属性提供保护的多少上拥有大量重要的控制权。尽管Python没有在语法上把private, protected、 friend或protected friend等特征内建于语言中,但是可以按你的需要严格地定制访问权。我们不可能涵盖所有的内容,但会在本章后面给你一些有关新式类属性访问的建议。