Python中的“public”或“private”属性? 什么是最好的方法?

在Python中,我有以下示例类:

class Foo: self._attr = 0 @property def attr(self): return self._attr @attr.setter def attr(self, value): self._attr = value @attr.deleter def attr(self): del self._attr 

正如你所看到的,我有一个简单的“私人”属性“_attr”和一个属性来访问它。 有很多代码来声明一个简单的私有属性,我认为它不尊重“KISS”哲学来声明所有属性。

那么,如果我不需要一个特定的getter / setter / deleter,为什么不把所有的属性声明为公共属性呢?

我的答案是:因为封装原则(OOP)否则说!

什么是最好的方法 ?

通常,Python代码努力遵守统一访问原则 。 具体而言,接受的方法是:

  • 直接暴露实例variables,例如允许foo.x = 0 ,而不是foo.set_x(0)
  • 如果你需要在方法中包装访问,不pipe什么原因,使用@property来保留访问语义。 也就是说, foo.x = 0现在调用foo.set_x(0)

这种方法的主要优点是调用者可以这样做:

 foo.x += 1 

即使代码可能真的在做:

 foo.set_x(foo.get_x() + 1) 

第一个陈述是可读性更高。 然而,通过属性,您可以添加(在开始或之后)使用第二种方法获得的访问控制。

请注意,以单个下划线开头的实例variables通常是私有的。 也就是说,下划线向其他开发者发出信号,认为这个值是私有的,不应该直接混淆它。 然而,语言中没有任何东西阻止他们直接搞乱它。

如果您使用双__x下划线(例如, __x ),Python会对名称进行一些混淆处理。 然而,这个variables仍然可以从类的外部通过混淆的名字访问。 这不是真正的私人。 这只是…更不透明。 并有反对使用双下划线的有效论据; 一方面可能会使debugging更加困难。

“dunder”(双下划线, __ )前缀阻止访问属性,除了通过访问器。

 class Foo(): def __init__(self): self.__attr = 0 @property def attr(self): return self.__attr @attr.setter def attr(self, value): self.__attr = value @attr.deleter def attr(self): del self.__attr 

一些例子:

 >>> f = Foo() >>> f.__attr # Not directly accessible. Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'Foo' object has no attribute '__attr' >>> '__attr' in f.__dir__() # Not listed by __dir__() False >>> f.__getattribute__('__attr') # Not listed by __getattribute__() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'Foo' object has no attribute '__attr' >>> f.attr # Accessible by implemented getter. 0 >>> f.attr = 'Presto' # Can be set by implemented setter. >>> f.attr 'Presto' >>> f.__attr = 'Tricky?' # Can we set it explicitly? >>> f.attr # No. By doing that we have created a 'Presto' # new but unrelated attribute, same name. 

很简单,面向对象的原则是错误的。 为什么这是一个漫长的讨论,导致火焰之战,可能是本网站的主题。 🙂

在Python中没有私有属性,你不能保护它们,这从来不是一个真正的问题。 所以不要。 简单! 🙂

然后是问题:如果你有一个领先的下划线或不。 而在这个例子中,你在这里你绝对不应该。 Python中的一个前导下划线是一种约定,表明某些东西是内部的,而不是API的一部分,您应该自行承担风险。 这显然不是这种情况,但这是一个常见而有用的惯例。

Python没有公共或私有属性。 所有的属性都可以访问所有的代码。

 self.attr = 0 #Done 

你的方法并没有使_attr是私人的,只是有点混淆。

正如其他人所说,Python中的私有属性仅仅是一个约定。 当属性被绑定,修改或删除时,应该使用property语法进行特殊处理。 Python的美妙之处在于,你可以通过使用正常的属性绑定(例如self.attr = 0 ,如果稍后决定要限制attr的值为0 <= attr <=100 ,您可以创build一个属性并定义一个方法来确保这个条件是真实的,而不必更改任何用户代码。

为了使一个属性是私人的,你只需要做self.__attr

 class Foo: self.__attr = 0 @property def attr(self): return self._attr @attr.setter def attr(self, value): self._attr = value @attr.deleter def attr(self): del self._attr 

在Python中,除非需要特殊的行为,否则不需要将其隐藏在访问器方法后面。 如果某个属性仅用于内部使用,请在其前面加上下划线。

属性的好处是它们给你一个非常酷的界面。 有时候,基于其他方式(如体重指数由体重和身高来定义)推导出属性是很方便的。 界面的用户当然不必知道这一点。

我比较喜欢Java这种显式的getter和setter方法。 方式更好。 🙂