繁体   English   中英

Python 中的私有方法

[英]Private methods in Python

我想在我的类中有一个函数,我将只在这个类的方法中使用它。 我不会在这些方法的实现之外调用它。 在 C++ 中,我会使用在类的私有部分中声明的方法。 在 Python 中实现这样一个函数的最佳方法是什么?

我正在考虑在这种情况下使用静态装饰器。 我可以使用没有任何装饰器和self词的函数吗?

Python 没有私有方法或属性的概念。 这完全取决于您如何实现您的课程。 但是您可以使用伪私有变量(名称修改); 任何以__ (两个下划线)开头的变量都成为伪私有变量。

文档中

由于类私有成员有一个有效的用例(即避免名称与子类定义的名称发生名称冲突),因此对这种称为名称修饰的机制的支持有限。 __spam形式的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_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

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

另外,请注意self仅按惯例是特殊的,而不是语言的任何特性。 实例方法,当作为实例的成员调用时,会隐式地将实例作为第一个参数传递,但在方法本身的实现中,从技术上讲,该参数可以命名为您想要的任何任意事物。 self只是为了便于理解代码的约定。 因此,在方法的签名中不包括self没有实际的功能影响,只会导致将隐式实例参数分配给签名中的下一个变量名。

这对于类方法当然是不同的,它接收类对象本身的实例作为隐式的第一个参数,而静态方法则根本不接收任何隐式参数。

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

但是,如果您决心实现私有属性/方法并且您愿意成为 unpythonic,您可以执行以下操作:

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

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

Python 只是不做私有的。 如果您愿意,您可以遵循约定并在名称前加上一个下划线,但其他编码人员必须以绅士的方式尊重这一点†

† 或绅士风度

你只是不这样做:

  • Pythonic 方法是不使用docstrings记录这些方法/成员,仅使用“真实”代码注释。 约定是在它们后面加上一个或两个下划线;

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

  • 据我所知,可以使用元类“隐藏”变量,但这违反了 Python 的整个哲学,所以我不会对此进行详细介绍。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM