以下是Python基础教程(第三版)P122原文
7.2.4 再谈隐藏
默认情况下,可从外部访问对象的属性.再来看一下前面讨论封装时使用的示例.
>>>c.name
‘SirLancelot’
>>> c.name=‘Sir Gumby’
>>> c.get_name()
‘Sir Gumby’
有些程序员认为这没问题,但有些程序员(如Smalltalk之父)认为这违反了封装原则.他们认为应该对外部完全隐藏对象的状态(即不能从外部访问它们).
…
…可将属性定义为私有.私有属性不能从对象外部访问,而只能通过存取器方法(如get_name和set_name)来访问.
C++和Java中使用private关键字修饰属性以达到隐藏的效果.
不同于两者,Python语言并没有相应关键字,所以需要新的方法,不过很简单:就是让方法或属性以两个下划线打头即可.
例如: def __function() 或者 self.__attribute
下面是一个自定义的Tool(工具类),包括了__material(工具材质)和__color(工具颜色)两种属性以及存取器方法:
class Tool:
def __init__(self, material='wood', color='green'): #默认值
self.__material = material
self.__color = color
def show(self):
print(self.__material, self.__color)
def set_material(self, material):
self.__material = material
def set_color(self, color):
self.__color = color
def get_material(self):
return self.__material
def get_color(self):
return self.__color
def __secret_show(self): #一个不可见的函数
print("I'm Hidden")
newTool = Tool()
newTool.show()
#
newTool.set_color("white")
newTool.set_material("paper")
newTool.show()
#
newTool.__color = "yellow"
newTool.__material = "gold"
newTool.show()
输出结果
wood green
paper white
paper white
说明使用存取器方法可以正常修改和访问属性,对不能从外部访问的属性不能直接赋值,否则会失败.
但是书中还提出了一个幕后处理方法:
P123
在类定义中,对所有已两个下划线打头的名称都进行转换,即在开头加上一个下划线和类名.
>>>Secretive._Secretive__inaccessible
<unbound method Secretive.__inaccessible>
只要知道这种幕后处理手法,就能从类外访问私有方法,然而不应这样做
…
总之,你无法禁止别人访问对象的私有方法和属性,但这种名称修改方式发出了强烈的信号,让他们不要这样做.
如果你不希望名称被修改,又想发出不要从外部修改属性或方法的信号,可用一个下划线打头.
…
例如,from module import 不会导入以一个下划线打头的名称.
…
对于成员变量(属性),有些语言支持多种私有程度.例如,Java支持4中不同的私有程度.Python没有提供这样的支持,不过从某种程度上说,以一个和两个下划线打头相当于两种不同的私有程度.
书中已经描述得非常清楚了,不再赘述,这里让我们尝试一下幕后方法的使用:
newTool._Tool__material="unknown"
newTool._Tool__color="dark"
newTool.show()
newTool._Tool__secret_show()
输出结果
unknown dark
I'm Hidden
是时候在私有函数的__doc__中加点"幽默"了
PS:喂,你丫刚刚在我们换衣服时偷看了吧(唐突)
def __FBI__WARNING(self):
'BIG BROTHER IS WATCHING YOU'
...
Do something