我想在我的班级中有一个函数,我将只在这个类的方法中使用它。我不会在这些方法的实现之外调用它。在C ++中,我将使用在类的私有部分中声明的方法。在python中实现这样一个函数的最佳方法是什么?我想在这种情况下使用静态装饰器。我可以使用没有任何装饰器和self
单词
答案 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的整个哲学,所以我不会详细介绍