为什么Python';s';私人';方法实际上不是私有的?

为什么Python';s';私人';方法实际上不是私有的?,python,python-2.7,encapsulation,information-hiding,Python,Python 2.7,Encapsulation,Information Hiding,Python使我们能够通过在名称前加双下划线在类中创建“private”方法和变量,如下所示:\uu myPrivateMethod()。那么,人们如何解释这一点呢 >>> class MyClass: ... def myPublicMethod(self): ... print 'public method' ... def __myPrivateMethod(self): ... print 'this is private!

Python使我们能够通过在名称前加双下划线在类中创建“private”方法和变量,如下所示:
\uu 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 "", line 1, in 
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方法

>>> obj.myPublicMethod()
public method
接下来,我尝试调用它的私有方法

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
这里一切看起来都很好;我们不能打电话给它。事实上,这是“私人的”。其实不是。在对象上运行dir()可以揭示python为所有“私有”方法神奇地创建的一个新的神奇方法

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
此新方法的名称始终是下划线,后跟类名,后跟方法名

>>> obj._MyClass__myPrivateMethod()
this is private!!
封装就这么多了,嗯

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

来自

严格地说,私人方法是不可取的 在他们的课堂之外,只要 不容易接近。没有 Python是真正私有的;内部,, 私有方法和 属性被破坏和分解 飞来飞去,让他们看起来 无法通过他们的名字访问。你 可以访问 MP3FileInfo类的名称 _MP3FileInfo\uuuu解析。承认这很有趣,然后承诺 永远不要,永远不要用真正的代码。 私有方法是私有的 原因,但就像世界上的许多其他事情一样 巨蟒,他们的隐私是 归根结底,这是一个惯例问题,而不是问题 力量


<> P>不是完全不能绕过任何语言成员的私密性(C++中的指针算术,.NET/java中的反射)。 关键是,如果您试图意外地调用私有方法,就会出现错误。但是如果你想射中自己的脚,那就去做吧


编辑:你不会试图通过OO封装来保护你的东西,是吗?

类。\uuu stuff命名约定让程序员知道他不打算从外部访问
\uu stuff
。“弄脏”这个名字使人们不太可能偶然做这件事


诚然,您仍然可以解决这个问题,它甚至比其他语言更容易(顺便说一句,其他语言也允许您这么做),但如果Python程序员关心封装,他不会这么做。

这只是语言设计的选择之一。在某种程度上,它们是合理的。他们做到了,所以你需要走很远的路去尝试调用这个方法,如果你真的非常需要它,你一定有一个很好的理由

obj._MyClass__myPrivateMethod()

调试挂钩和测试作为可能的应用程序出现在脑海中,当然要负责任地使用。

常用的短语是“我们在这里都是同意的成年人”。通过预加一个下划线(不公开)或双下划线(隐藏),您告诉类的用户您希望该成员以某种方式“私有”。但是,您相信其他人会负责任地行事并尊重这一点,除非他们有令人信服的理由不这样做(例如调试器、代码完成)


如果您确实必须拥有私有的东西,那么您可以在扩展中实现它(例如,在C for CPython中)。然而,在大多数情况下,您只需学习python式的处理方式。

名称置乱用于确保子类不会意外地重写其超类的私有方法和属性。它的设计并不是为了防止外界故意进入

例如:

>>> 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}

当然,如果两个不同的类具有相同的名称,则会发生故障。

当模块属性名称以一个下划线开头时(例如,_foo),会出现类似的行为

使用
from*
方法时,命名为这样的模块属性不会复制到导入模块中,例如:

from bar import *

然而,这是一种惯例,而不是语言限制。这些不是私人属性;它们可以被任何进口商引用和操纵。有人认为,正因为如此,Python无法实现真正的封装。

当我第一次从Java来到Python时,我痛恨这一点。它把我吓死了

obj._MyClass__myPrivateMethod()
今天,它可能只是Python中我最喜欢的一件事

我喜欢呆在一个平台上,在这个平台上,人们彼此信任,不需要在他们的代码周围筑起难以穿透的墙。在强封装语言中,如果一个API有一个bug,并且您已经找出了哪里出了问题,您可能仍然无法解决它,因为所需的方法是私有的。在Python中,态度是:“当然”。如果你认为你了解情况,也许你甚至读过,那么我们只能说“祝你好运!”

请记住,封装与“安全性”或让孩子远离草坪的关系甚微。这只是另一种模式,应该用来使代码库更容易理解。

私有函数示例
对于Python 3.4,这是一种行为:

>>> class Foo:
        def __init__(self):
                pass
        def __privateMethod(self):
                return 3
        def invoke(self):
                return self.__privateMethod()


>>> help(Foo)
Help on class Foo in module __main__:

class Foo(builtins.object)
 |  Methods defined here:
 |
 |  __init__(self)
 |
 |  invoke(self)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

 >>> f = Foo()
 >>> f.invoke()
 3
 >>> f.__privateMethod()
 Traceback (most recent call last):
   File "<pyshell#47>", line 1, in <module>
     f.__privateMethod()
 AttributeError: 'Foo' object has no attribute '__privateMethod'
>>类Foo:
定义初始化(自):
通过
def_u_私有方法(self):
返回3
def调用(自我):
返回self.\u privateMethod()
>>>帮助(Foo)
模块_; main中有关Foo类的帮助:
类Foo(内置的.object)
|此处定义的方法:
|
|_uuu初始(自我)
|
|调用(自我)
|
|  ----------------------------------------------------------------------
|此处定义的数据描述符:
|
|_uuudict__
|实例变量字典(如果已定义)
|
|_uuuweakref__
|对象的弱引用列表(如果已定义)
>>>f=Foo()
>>>f.调用()
3.
>>>f._u私有方法()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
f、 _uuuprivateMethod()
AttributeError:“Foo”对象没有属性“\uu privateMethod”

注tha