San*_*nda 49 python oop encapsulation properties
在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
Run Code Online (Sandbox Code Playgroud)
如您所见,我有一个简单的"私有"属性"_attr"和一个访问它的属性.有很多代码来声明一个简单的私有属性,我认为它不尊重"KISS"哲学来声明所有属性.
那么,如果我不需要特定的getter/setter/deleter,为什么不将所有属性声明为公共属性?
我的答案是:因为封装原则(OOP)说不然!
什么是最好的方法 ?
Bri*_*per 83
通常,Python代码努力遵循统一访问原则.具体而言,接受的方法是:
foo.x = 0,不允许foo.set_x(0)@property,这将保留访问语义.也就是说,foo.x = 0现在调用foo.set_x(0).这种方法的主要优点是调用者可以这样做:
foo.x += 1
Run Code Online (Sandbox Code Playgroud)
即使代码可能真的在做:
foo.set_x(foo.get_x() + 1)
Run Code Online (Sandbox Code Playgroud)
第一个语句无限可读.但是,对于属性,您可以添加(在开头或稍后)使用第二种方法获得的访问控制.
另请注意,以单个下划线开头的实例变量通常是私有的.也就是说,下划线向其他开发人员发出信号,表示您认为该值是私有的,并且他们不应该直接混淆它; 但是,语言中的任何内容都不能阻止他们直接搞乱它.
如果你使用双前导下划线(例如__x),Python会对名称进行一些模糊处理.但是,仍然可以通过其混淆的名称从类外部访问该变量.这不是真正私密的.它只是......更不透明.并且有反对使用双下划线的有效论据; 首先,它可以使调试更加困难.
bra*_*ese 16
"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
Run Code Online (Sandbox Code Playgroud)
一些例子:
>>> 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.
Run Code Online (Sandbox Code Playgroud)
        Len*_*bro 10
很简单,OOP原则是错误的.为什么这是一个长期的讨论,导致火焰战争,可能是该网站的主题.:-)
在Python中没有私有属性,你无法保护它们,这绝不是一个真正的问题.所以不要.简单!:)
接下来的问题是:你是否应该有一个领先的下划线.在你在这里的例子中你绝对不应该.Python中的一个主要下划线是一种约定,表明某些内容是内部的,而不是API的一部分,并且您应该自担风险使用它.这显然不是这里的情况,但它是一种常见且有用的惯例.
Python没有公共OR私有属性.所有代码都可以访问所有属性.
self.attr = 0 #Done
Run Code Online (Sandbox Code Playgroud)
你的方法并没有以任何方式使_attr私有,这只是一些混淆.
请参阅此链接:https : //docs.python.org/2/tutorial/classes.html
Python 中不存在只能从对象内部访问的“私有”实例变量。但是,大多数 Python 代码都遵循一个约定:带有下划线前缀的名称(例如 _spam)应该被视为 API 的非公开部分(无论是函数、方法还是数据成员) . 它应被视为实施细节,如有更改,恕不另行通知。
由于类私有成员有一个有效的用例(即避免名称与子类定义的名称的名称冲突),因此对这种称为名称修改的机制的支持有限。任何 __spam 形式的标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为 _classname__spam,其中 classname 是当前类名,去掉了前导下划线。只要它出现在类的定义中,就可以不考虑标识符的句法位置来完成这种修改。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           69074 次  |  
        
|   最近记录:  |