为什么Python';s';私人';方法实际上不是私有的?
Python使我们能够通过在名称前加双下划线在类中创建“private”方法和变量,如下所示:为什么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!
\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