为什么Python的“私有”方法实际上不是私有的?

Python使我们能够在类中创build'private'方法和variables,方法是在名称前加双下划线,如下所示: __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() 

我在那里做的是用公共方法和私有方法创build一个类并实例化它。

接下来,我将其称为公共方法。

 >>> obj.myPublicMethod() public method 

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

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

一切看起来都不错 我们无法称呼它。 事实上,这是“私人的”。 那么,实际上不是。 在对象上运行dir()揭示了python为所有“私有”方法创build的神奇方法。

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

这个新方法的名字总是一个下划线,后面是类名,后面跟着方法名。

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

这么多封装,呃?

无论如何,我总是听说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} 

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

私人function的例子

 import re import inspect class MyClass : def __init__(self) : pass def private_function ( self ) : try : function_call = inspect.stack()[1][4][0].strip() # See if the function_call has "self." in the begining matched = re.match( '^self\.', function_call ) if not matched : print 'This is Private Function, Go Away' return except : print 'This is Private Function, Go Away' return # This is the real Function, only accessible inside class # print 'Hey, Welcome in to function' def public_function ( self ) : # i can call private function from inside the class self.private_function() ### End ### 

http://www.faqs.org/docs/diveintopython/fileinfo_private.html

严格来说,私人方法在课外是可以访问的,只是不容易访问。 Python中没有什么是真正的私有的; 在内部,私有方法和属性的名称在运行中被破坏和解除,使得它们的名字看起来不可访问。 您可以通过名称_MP3FileInfo__parse访问MP3FileInfo类的__parse方法。 承认这是有趣的,然后承诺永远不会在真正的代码。 私有方法是私有的,但是和Python中的许多其他方法一样,它们的私有性最终是一个约定,而不是强制。

当我第一次从Java到Python时,我讨厌这个。 它吓死我了

今天,它可能只是我最爱 Python的一件事情。

我喜欢在一个平台上,人们相互信任,不觉得他们需要在代码周围build立不可逾越的围墙。 在强封装语言中,如果一个API有一个错误,并且已经找出错误,那么可能仍然无法解决它,因为所需的方法是私有的。 在Python中,态度是:“确定”。 如果你认为你了解情况,也许你已经读了,那么我们只能说“祝你好运”。

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

常用的短语是“我们都在这里同意大人”。 通过预先设置一个下划线(不要公开)或双下划线(隐藏),你告诉你的class级的用户,你打算这个成员以某种方式是“私人的”。 但是,你相信所有其他人都要负责任地行事,尊重他人,除非他们有一个令人信服的理由(例如debugging器,代码完成)。

如果你真的必须拥有一些私有的东西,那么你可以在扩展中实现它(例如在C for CPython中)。 然而,在大多数情况下,你只是学习Pythonic的做事方式。

它不像你绝对无法绕过任何语言的成员的私密性(C ++中的指针算术,.NET / Java中的思考)。

问题是,如果你偶然打电话给私人方法,你会得到一个错误。 但是如果你想用脚射自己,那么就去做吧。

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

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

以这种名称命名的模块属性在使用from*方法时不会被复制到导入模块中,例如:

 from bar import * 

但是,这是一个惯例而不是语言约束。 这些不是私人属性; 他们可以被任何import商引用和操纵。 有人认为,正因为如此,Python不能实现真正的封装。

这只是这些语言deviseselect之一。 在某种程度上,他们是有道理的。 他们这样做,所以你需要远离你的方式去尝试和调用这个方法,如果你确实需要这个方法,那你一定有一个很好的理由!

debugging挂钩和testing可以想象成可能的应用程序,当然使用负责任的。

class.__stuff命名约定让程序员知道他并不是要从外面访问__stuff 。 这个名字使人不可能任何人不小心做到这一点。

诚然,你仍然可以解决这个问题,它比其他语言(也可以让你这样做)更容易,但是如果他关心封装,没有一个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' 

https://docs.python.org/3/tutorial/classes.html#tut-private

请注意,规则的devise主要是为了避免事故; 仍然可以访问或修改被认为是私有的variables。 这在特殊情况下甚至是有用的,比如在debugging器中。

即使这个问题很老,我希望我的摘录可能会有所帮助。