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()

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

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

>>> 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(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

此新方法的名称始终是下划线,后跟类名,后跟方法名。

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

封装就这么多了,是吗?

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


当前回答

常用的短语是“我们都是成年人”。通过在前面加上一个下划线(不要暴露)或双下划线(隐藏),您可以告诉类的用户您希望成员以某种方式“私有”。然而,您相信其他人都会表现得负责任并尊重这一点,除非他们有令人信服的理由不这样做(例如,调试器和代码完成)。

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

其他回答

这只是语言设计的选择之一。在某种程度上,它们是合理的。他们做到了这一点,所以你需要尽可能地尝试调用该方法,如果你真的非常需要它,你必须有一个很好的理由!

调试钩子和测试是可能出现的应用程序,当然要负责任地使用。

专用函数示例

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 beginning
            matched = re.match( '^self\.', function_call)
            if not matched:
                print 'This is a private function. Go away.'
                return
        except:
            print 'This is a private function. Go away.'
            return

        # This is the real function, only accessible inside the class #
        print 'Hey, welcome in to the function.'

    def public_function(self):
        # I can call a private function from inside the class
        self.private_function()

### End ###

关于私有方法和属性最重要的问题是告诉开发人员不要在类外部调用它,这就是封装。人们可能误解了封装的安全性。当你故意使用你提到的(下面)语法时,你不需要封装。

obj._MyClass__myPrivateMethod()

我是从C#迁移过来的,起初这对我来说也很奇怪,但过了一段时间,我发现只有Python代码设计者对OOP的思考方式不同。

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

据我所知,他们不可能是私人的。如何才能强制实施隐私?

显而易见的答案是“私有成员只能通过self访问”,但这行不通——self在Python中并不特殊。它只是函数的第一个参数的常用名称。

这并不是说在任何语言(C++中的指针算法和.NET/Java中的反射)中都无法避免成员的隐私。

关键是,如果您尝试意外调用私有方法,就会出现错误。但如果你想射自己的脚,那就去做吧。

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