Python中的私有方法

时间:2013-06-19 14:08:40

标签: python oop static-methods

我想在我的班级中有一个函数,我将只在这个类的方法中使用它。我不会在这些方法的实现之外调用它。在C ++中,我将使用在类的私有部分中声明的方法。在python中实现这样一个函数的最佳方法是什么?我想在这种情况下使用静态装饰器。我可以使用没有任何装饰器和self单词

的函数

5 个答案:

答案 0 :(得分:22)

Python没有私有方法或属性的概念,而是关于如何实现类的。但是你可以使用伪私有变量(名称修改),任何以__开头的变量(两个下划线)都会成为一个伪私有变量。

来自docs

  

由于类私有成员有一个有效的用例(即   避免名字冲突的名称与子类定义的名称,在那里   对这种机制的支持是有限的,称为名称修改。任何   __spam形式的标识符(至少两个主要下划线,at   大多数一个尾随下划线)在文本上被替换为   _classname__spam,其中classname是当前类名,其中前导下划线被剥离。这种破坏是不加考虑的   到标识符的句法位置,只要它发生   在一个类的定义内。

class A:
    def __private(self):
       pass

所以__private现在实际上变成了_A__private

静态方法的例子:

>>> class A:
...     @staticmethod         #not required in py3.x
...     def __private():
...         print 'hello'
...         
>>> A._A__private()
hello

答案 1 :(得分:6)

Python没有像许多其他语言那样的“私有”概念。它建立在同意的成人原则之上,该原则表明您的代码的用户将负责任地使用它。按照惯例,以单引号或双引号下划线开头的属性将被视为内部实现的一部分,但它们实际上并未对用户隐藏。双下划线会导致属性名称的名称重写。

另外,我会注意到self只是按照惯例而言是特殊的,而不是语言的任何特征。例如,当作为实例的成员调用它们时,它们隐式地将实例作为第一个参数传递,但是在方法本身的实现中,该参数在技术上可以命名为您想要的任意事物。 self只是易于理解代码的惯例。因此,除了使隐式实例参数分配给签名中的下一个变量名之外,在方法签名中不包括self没有实际的功能效果。对于类方法来说,这当然是不同的,它们将类对象本身的实例作为隐式的第一个参数接收,而静态方法则根本不接收隐式参数。

答案 2 :(得分:3)

这里有许多很棒的东西,使用前导下划线进行混淆。就个人而言,我从语言设计决策中受益匪浅,因为它减少了理解和使用新模块所需的时间。

但是,如果您决定实施私有属性/方法,而您又愿意采用单一方式,那么您可以采取以下措施:

from pprint import pprint


# CamelCase because it 'acts' like a class
def SneakyCounter():

    class SneakyCounterInternal(object):

        def __init__(self):
            self.counter = 0

        def add_two(self):
            self.increment()
            self.increment()

        def increment(self):
            self.counter += 1

        def reset(self):
            print 'count prior to reset: {}'.format(self.counter)
            self.counter = 0

    sneaky_counter = SneakyCounterInternal()

    class SneakyCounterExternal(object):

        def add_two(self):
            sneaky_counter.add_two()

        def reset(self):
            sneaky_counter.reset()

    return SneakyCounterExternal()


# counter attribute is not accessible from out here
sneaky_counter = SneakyCounter()

sneaky_counter.add_two()
sneaky_counter.add_two()
sneaky_counter.reset()

# `increment` and `counter` not exposed (AFAIK)
pprint(dir(sneaky_counter))

很难想象你想要这样做的情况,但这是可能的。

答案 3 :(得分:2)

Python只是不私有。如果你愿意,你可以遵循惯例,并在名称前加上单下划线,但是由其他程序员以绅士风格†来尊重它

†或绅士

答案 4 :(得分:1)

你只是不这样做:

  • pythonic方法是不使用docstrings记录那些方法/成员,只使用“真实”代码注释。惯例是向它们附加单个或双重下划线;

  • 然后你可以在你的成员面前使用双下划线,这样你就可以将它们放在类的本地(它主要是名称错误,即类之外的成员的真实姓名变为:{{1} })。在使用继承时避免冲突或在类的子级之间创建“私有空间”是有用的。

  • AFAICT,可以使用元类“隐藏”变量,但这违反了python的整个哲学,所以我不会详细介绍