python - 为什么 Python 的 'private' 方法实际上不是私有(private)的?

标签 python encapsulation information-hiding

Python 使我们能够通过在名称前添加双下划线来在类中创建“私有(private)”方法和变量,例如:__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()

我用公共(public)方法和私有(private)方法创建了一个类并实例化它。

接下来,我调用它的公共(public)方法。

>>> obj.myPublicMethod()
public method

接下来,我尝试调用它的私有(private)方法。

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

这里的一切看起来都不错;我们无法调用它。事实上,它是“私有(private)的”。嗯,实际上并非如此。在对象上运行 dir() 揭示了一种新的神奇方法,Python 神奇地为你的所有“私有(private)”方法创建了这种方法。

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

这个新方法的名称始终是一个下划线,后跟类名,然后是方法名。

>>> obj._MyClass__myPrivateMethod()
this is private!!

封装这么多,嗯?

无论如何,我一直听说 Python 不支持封装,那么为什么还要尝试呢?什么给了?

最佳答案

名称加扰用于确保子类不会意外覆盖其父类(super class)的私有(private)方法和属性。它并非旨在防止从外部故意访问。

例如:

>>> class Foo(object):
...     def __init__(self):
...         self.__baz = 42
...     def foo(self):
...         print self.__baz
...     
>>> class Bar(Foo):
...     def __init__(self):
...         super(Bar, self).__init__()
...         self.__baz = 21
...     def bar(self):
...         print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}

当然,如果两个不同的类具有相同的名称,它就会崩溃。

关于python - 为什么 Python 的 'private' 方法实际上不是私有(private)的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70528/

相关文章:

c++ - 随机数生成和封装

c# - 界面的目的是隐藏信息吗?

java - 如何使 java.lang.reflect.Proxy.newProxyInstance() 返回的对象扩展其他类

python - 使用 pandas groupby + apply 和 condensing groups 计算平均值的更快方法

Python Selenium(等待框架、元素查找)

python - 我怎样才能摆脱这个 bash 命令后创建的新行?

java - BitmapFactory.Options 中没有封装

c++ - 一种更简单的 pimpl 形式

language-agnostic - 通过信息隐藏进行有效封装的绝妙例子?

python - sklearn LatentDirichletAllocation 新语料库的主题推理