Python中的私有变量和方法

70 投票
4 回答
131725 浏览
提问于 2025-04-16 02:10

在Python中,我什么时候应该用_foo(一个下划线)或者__bar(两个下划线)来表示私有成员和方法呢?

4 个回答

11

双下划线。这会让变量名变得复杂。虽然这个变量还是可以访问,但通常这样做不是个好主意。

单下划线用来表示半私有(告诉其他Python开发者“只有在绝对必要时才可以修改”),而双下划线则表示完全私有。

44

双下划线的作用是让名字变得复杂,这样外部就不能简单地通过 __fieldName 来访问它,这正是你想要的,因为它应该是私有的。(不过其实还是不难访问到这个字段。)

class Foo:
    def __init__(self):
        self.__privateField = 4;
        print self.__privateField # yields 4 no problem

foo = Foo()
foo.__privateField
# AttributeError: Foo instance has no attribute '__privateField'

你可以通过 _Foo__privateField 来访问它。但这就像在大喊“我很私密,别碰我”,总比什么都没有好。

72

请注意,Python中并没有所谓的“私有方法”。双下划线只是用来改变名字的方式:

>>> class A(object):
...     def __foo(self):
...         pass
... 
>>> a = A()
>>> A.__dict__.keys()
['__dict__', '_A__foo', '__module__', '__weakref__', '__doc__']
>>> a._A__foo()

因此,当你需要这种名字改变的效果时,使用__前缀是有用的,比如为了避免在继承链上出现名字冲突。对于其他情况,我认为单下划线会更好。

补充一下,关于__的混淆,PEP-8对此有很清楚的说明:

如果你的类是打算被继承的,并且你有一些属性不希望子类使用,考虑用双下划线开头而不加结尾的下划线来命名它们。这会触发Python的名字改变算法,把类名变成属性名。这样可以避免子类意外地包含同名属性而导致的冲突。

注意3:并不是每个人都喜欢名字改变的方式。要在避免意外名字冲突和高级用户可能使用的需求之间找到平衡。

所以,如果你不担心子类会意外地重新定义同名的方法,就不用使用这个方式。

撰写回答