Python中的私有方法
我希望在我的类中有一个函数,我将只在这个类的方法中使用它。我不会在这些方法的实现之外调用它。在C++中,我将使用类的私有部分中声明的方法。在python中实现这样一个函数的最佳方法是什么?我正在考虑在这个案例中使用静态装饰器。我可以在没有任何装饰符的情况下使用函数吗?Python不像许多其他语言那样具有“私有”的概念。它建立在成年人同意的原则之上,即代码的用户将负责任地使用它。按照惯例,以单下划线或双下划线开头的属性将被视为内部实现的一部分,但它们实际上不会对用户隐藏。但是,双下划线将导致属性名称的名称混乱 另外,我要提醒你的是,Python中的私有方法,python,oop,static-methods,Python,Oop,Static Methods,我希望在我的类中有一个函数,我将只在这个类的方法中使用它。我不会在这些方法的实现之外调用它。在C++中,我将使用类的私有部分中声明的方法。在python中实现这样一个函数的最佳方法是什么?我正在考虑在这个案例中使用静态装饰器。我可以在没有任何装饰符的情况下使用函数吗?Python不像许多其他语言那样具有“私有”的概念。它建立在成年人同意的原则之上,即代码的用户将负责任地使用它。按照惯例,以单下划线或双下划线开头的属性将被视为内部实现的一部分,但它们实际上不会对用户隐藏。但是,双下划线将导致属性名
self
只是按照惯例,而不是语言的任何特征。例如实例方法,当作为实例的成员调用时,它们会作为第一个参数隐式地传递给实例,但在方法本身的实现中,该参数在技术上可以被命名为任何您想要的任意对象self
只是一种便于理解代码的惯例。因此,在方法的签名中不包含self
,除了导致隐式实例参数被分配给签名中的下一个变量名之外,没有实际的功能效果。当然,对于类方法(将类对象本身的实例作为隐式第一个参数接收)和静态方法(根本不接收隐式参数),这两种方法是不同的。您只是不这样做:
- pythonic的方法是不使用docstring记录那些方法/成员,只使用“真实”代码注释。惯例是在它们后面加上一个或两个下划线
- 然后,您可以在成员前面使用双下划线,使其成为类的本地名称(主要是名称混乱,即类外成员的真实名称变为:
)。在使用继承时避免冲突,或者在类的子类之间创建“私有空间”,这很有用instance.\uu classname\u membername
- 首先,可以使用元类“隐藏”变量,但这违反了python的全部理念,因此我将不详细介绍
\uuu
(两个下划线)的变量都将成为伪私有变量
从:
因为类私有成员有一个有效的用例(即
避免名称与子类定义的名称发生名称冲突)
对这种机制的支持是有限的,称为名称混乱。任何
垃圾邮件格式的标识符(至少两个前导下划线,至少
大多数尾随下划线)在文本上替换为
\u classname\uu spam
,其中classname是当前类名,去掉前导下划线。这种弄脏是不加考虑的
标识符的语法位置,只要它出现
在类的定义中
所以\u private
现在实际上变成了\u A\u private
静态方法示例:
>>> class A:
... @staticmethod #not required in py3.x
... def __private():
... print 'hello'
...
>>> A._A__private()
hello
Python只是不做私有的。如果您愿意,您可以遵循惯例,在名称前面加一个单下划线,但这取决于其他编码人员是否以绅士风度†的方式尊重这一点
†或温柔的女人这里有很多很棒的东西,用前导下划线进行模糊处理。就我个人而言,我从语言设计决策中受益匪浅,因为它减少了理解和使用新模块所需的时间 但是,如果您决心实现私有属性/方法,并且愿意不使用pythonic,那么您可以按照以下思路做一些事情:
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中没有真正的“私有”方法。请看-更具体地说,.我想问的是做这件事的好方式静态方法和“私有”方法是两件不同的事情。。。你能解释一下你到底想要什么吗?您想要一个既静态又私有的方法吗?好的样式是在方法名称前加下划线。双下划线会激活名称混乱。这绝对不同于Private这正是我所说的:你不做,但你使用约定!您可以通过元类混淆属性访问,也可以创建只读属性,并使用装饰器或元类实现private/setter/getter模式,但是混淆某些东西的唯一方法是将其隐藏在C扩展中,而有些人确实无法从Python代码中获得。我可以只做def_uprivate()吗:没有自我通过?然后在我的类中调用它_private()。我可以在类之外访问这个函数吗?@freude您已经将它定义为一个静态方法,并将其称为:
a.\u a\u private()
在这种情况下,静态是什么意思?\u
的目标是避免与子类发生冲突。它通过名称混乱来实现这一点,将类名合并到变量中。这会使变量更难找到和访问,这是一个副作用。您确实需要一个装饰器。Python专门处理类方法的第一个参数,因此除非应用@staticmethod
或类似的修饰符,否则会出现错误。这是一个不使用Python的好例子,但很有教育意义)
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))