我正在做一些关于在使用Python的面向对象编程中使用封装的研究,而我偶然发现了关于封装属性如何工作以及如何使用它们的各种观点。 我已经编写了这段代码,这只会使事情变得更加混乱:
class Dog:
def __init__(self,weight):
self.weight = weight
__color =''
def set_color(self,color):
self.__color = color
def get_color(self):
print(self.__color)
rex = Dog(59)
rex.set_color('Black')
rex.get_color()
rex.color = 'White'
rex.__color = rex.color
print(rex.__color)
rex.get_color()
结果是:
>Black
>White
>Black
我知道这背后的原因是因为当我们执行分配rex.__color = rex.color
时,会创建一个新属性,该属性不指向实例化real __color
的{{1}}。
我的问题是:
答案 0 :(得分:1)
在没有属性的语言(例如Java)中,这种用法非常普遍,以至于has become a standard,并且所有已经有getter / setter的框架假定。
但是,在python中,您可以具有 properties ,这些属性本质上是吸气剂/设置剂,可以在以后添加它们而无需更改使用变量的代码。因此,没有理由在python中执行此操作。将这些字段用作公共字段,并在以后发生更改时添加属性。
注意:在“私有”变量中使用单下划线而不是双下划线。不仅是通用约定,而且解释器对双下划线的处理也不同。
答案 1 :(得分:0)
封装不是关于数据隐藏,而是关于将状态和行为保持在一起。数据隐藏是通过防止直接访问内部状态来强制执行封装的一种方法,因此客户端代码必须改为使用(公共)方法。这里的要点是:1 /允许对象保持一致的状态(检查值,最终相应地更新状态的其他部分,等等)和2 /允许实现更改(内部状态/私有方法)而不会破坏客户端代码。
像Java这样的语言不支持计算属性,因此,维护此类语言封装的唯一方法是使所有属性受保护或私有,并最终提供访问器。 las,有些人从来没有正确地使用“最终”部分,而是坚持为所有属性提供读/写访问器,这完全是胡说八道。
Python通过描述符协议(通常通过通用的property
类型对计算属性提供了强大的支持,但是您当然可以编写自己的描述符),因此不需要显式的getter / setter方法-您的设计要求某个类应提供可公开访问的属性作为其API的一部分,您始终可以仅从一个公共属性开始,如果在某个时候需要更改实现,则可以将其替换为计算属性。
这并不意味着您应该公开所有属性!!! -大多数情况下,您将拥有“实现属性”(支持内部状态但绝不支持内部状态的属性)类API的一部分),您肯定想保持对它们的保护(通过在它们前面加一个下划线作为前缀)。
请注意,Python不会尝试从技术上强制执行隐私,它只是一个命名约定,您不能阻止客户端代码访问内部状态。不用担心,很少有人愚蠢地在没有充分理由的情况下绕过官方API,然后他们知道自己的代码可能会破坏某些东西并承担所有后果。