“public” or “private” attribute in Python ? What is the best way?
在python中,我有以下示例类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
如您所见,我有一个简单的"private"属性"attr"和一个访问它的属性。有很多代码可以声明一个简单的私有属性,我认为这样声明所有属性并不尊重"吻"哲学。
那么,如果我不需要一个特定的getter/setter/deleter,为什么不将我的所有属性声明为公共属性呢?
我的答案是:因为封装原理(oop)说的不是这样!
最好的方法是什么?
通常,python代码力求遵循统一的访问原则。具体来说,公认的方法是:
- 直接公开实例变量,例如,允许
foo.x = 0 ,而不是foo.set_x(0) 。 - 如果您出于任何原因需要将访问包装在方法中,请使用
@property ,它保留了访问语义。也就是说,foo.x = 0 现在调用foo.set_x(0) 。
这种方法的主要优点是调用者可以这样做:
1 | foo.x += 1 |
即使代码可能真的在做:
1 | foo.set_x(foo.get_x() + 1) |
第一条语句的可读性无限强。然而,使用属性,您可以添加(在开始时,或稍后)使用第二种方法获得的访问控制。
请注意,以单个下划线开头的实例变量通常是私有的。也就是说,向其他开发人员发出的下划线信号表明,您认为价值是私有的,他们不应该直接处理它;但是,语言中没有任何内容阻止他们直接处理它。
如果使用双前导下划线(例如,
"dunder"(双下划线,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
一些例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | >>> 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. |
很简单,OOP原则是错误的。为什么这是一个长期的讨论,导致火焰大战,可能是这个网站的主题以外。-)
在Python中,没有私有属性,您不能保护它们,这从来不是真正的问题。所以不要。放松!:)
接下来的问题是:您是否应该有一个前导下划线。在这里的例子中,你绝对不应该。python中的一个前导下划线是一种惯例,它表明某些东西是内部的,而不是API的一部分,并且您应该自担风险地使用它。这显然不是这里的情况,但这是一个常见且有用的惯例。
python没有公共或私有属性。所有代码都可以访问所有属性。
1 | self.attr = 0 #Done |
你的方法并没有使你的隐私化,只是有点模糊。
正如其他人所说,Python中的私有属性只是一种约定。在绑定、修改或删除属性时,应使用
湖本链接:http://///classes.html docs.python.org教程2
9.6。私有变量和一流的本地参考
"私人"是不能访问实例变量,除了从内部在Python中的对象不存在。然而,他们有一个会议,是由Python代码:A字头最有下划线的名称(例如_垃圾邮件)应处理作为一个非公开的API的一部分(无论它是一个函数,a的方法或数据成员)。它应该被视为在没有实施细节与主题的变更通知。
因为有一个有效的用例(即私有成员的类的名称,以避免冲突的姓名名称定义subclasses)有限公司的支持,有这样一个机制,所谓的名字。任何形式的垃圾邮件的_ _标识符(至少两个尾随领先的下划线,下划线,在一个指定的textually)是没有_ _ _ classname是垃圾邮件,在领先的流类名称有下划线的(S)的剥离。这是他做不到"句法位置标识符时,只要它在一类的定义。
要使属性私有化,只需执行EDOCX1[10]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
属性的好处在于它们为您提供了一个非常酷的界面。有时,基于其他属性(即体重指数由体重和身高定义)来推导属性很方便。当然,界面的用户不必知道这一点。
我更喜欢使用显式的吸收器和设置器,如Java IE.Way-Neer-ER。:)
在Python中,除非需要属性之外的特殊行为,否则不需要将其隐藏在访问器方法后面。如果属性仅供内部使用,请在其前面加下划线。