Python 允许我们在类中创建“私有”方法和变量,只需在名称前面添加双下划线即可,如下所示:__myPrivateMethod()。那么,如何解释这一点呢?
__myPrivateMethod()
>>>> class MyClass: ... def myPublicMethod(self): ... print 'public method' ... def __myPrivateMethod(self): ... print 'this is private!!' ... >>> obj = MyClass() >>> obj.myPublicMethod() public method >>> obj.__myPrivateMethod() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: MyClass instance has no attribute '__myPrivateMethod' >>> dir(obj) ['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod'] >>> obj._MyClass__myPrivateMethod() this is private!!
这是怎么回事?!
我会向那些不太明白的人稍微解释一下。
>>> class MyClass: ... def myPublicMethod(self): ... print 'public method' ... def __myPrivateMethod(self): ... print 'this is private!!' ... >>> obj = MyClass()
我创建一个具有公共方法和私有方法的类并实例化它。
接下来,我调用它的公共方法。
>>> obj.myPublicMethod() public method
接下来,我尝试调用它的私有方法。
>>> obj.__myPrivateMethod() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: MyClass instance has no attribute '__myPrivateMethod'
这里一切看起来都很好;我们无法调用它。事实上,它是“私有的”。嗯,实际上它不是。dir()在对象上运行会显示一种新的神奇方法,Python 会神奇地为所有“私有”方法创建这种方法。
dir()
>>> dir(obj) ['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
这个新方法的名称总是一个下划线,后跟类名,后跟方法名。
>>> obj._MyClass__myPrivateMethod() this is private!!
封装就这么多,是吧?
无论如何,我一直听说 Python 不支持封装,那为什么还要尝试呢?到底是怎么回事?
您在 Python 中观察到的有关“私有”方法和名称修改的行为确实是故意的,并且用于特定目的,而不是违反封装。让我们分解一下关键点以更好地理解此行为:
在 Python 中,在方法或属性名称前使用双下划线 ( __) 会触发名称改编。名称改编主要是为了避免意外访问和覆盖子类中的属性。当您定义诸如 之类的方法时__myPrivateMethod,Python 会在内部将其重命名为_MyClass__myPrivateMethod。进行这种重命名是为了降低与子类使用的名称意外冲突的可能性。
__
__myPrivateMethod
_MyClass__myPrivateMethod
当您尝试__myPrivateMethod直接访问 的实例时MyClass,Python 找不到名为 的属性,__myPrivateMethod因为它已被破坏。这就是您得到 的原因AttributeError。
MyClass
AttributeError
尽管通过名称修改实现了表面上的隐私,但 Python 并不强制执行严格的访问控制。相反,它提供了一种使用修改后的名称直接访问这些“私有”方法的方法。当您使用dir(obj)并查看_MyClass__myPrivateMethod列表时会显示这一点。
dir(obj)
Python 的封装方法更多的是约定俗成,而不是严格执行。单下划线 ( _) 前缀通常用于指示“受保护”的属性或方法(供内部使用或供子类使用)。双下划线 ( __) 用于名称修改,以避免意外的名称冲突。
_
尽管 Python 不像其他一些语言那样强制执行封装,但它仍然鼓励这样做,原因如下:
Python 的封装方法虽然在访问控制方面并不严格,但提供了名称修改等机制来支持良好的编码实践。虽然可以使用修改后的名称访问“私有”方法,但除非绝对必要,否则通常不建议这样做,因为这会导致代码更难维护且更容易出错。相反,遵守命名约定并对“受保护”的方法和属性使用单下划线通常足以在 Python 中实现封装。