真实世界中的python封装属性

Python encapsulated attributes on real world

我正在做一些关于在使用python的面向对象编程中使用封装的研究,我遇到了一个关于封装属性如何工作以及如何使用它们的混合意见的主题。我已经对这段代码进行了编程,这段代码只会让我更加困惑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()

结果是:

1
2
3
>Black
>White
>Black

我理解这背后的原因是,当我们执行分配rex.__color = rex.color时,会创建一个新属性,它不指向实例Dogreal __color。我的问题是:

  • 这是一个常见的场景吗?
  • 私有属性真的经常被使用吗?


在没有属性(如Java)的语言中,这是很常见的,它已经成为一个标准,并且所有的框架都假定吸气剂/定位器已经存在。

但是,在Python中,您可以拥有属性,这些属性本质上是getter/setter,可以在以后添加,而不更改使用变量的代码。所以,没有理由用Python来实现。将字段用作公共字段,并在以后发生更改时添加属性。

注意:在"private"变量中使用单下划线而不是双下划线。这不仅是常见的约定,而且解释程序处理双下划线的方式也不同。


封装不是关于数据隐藏,而是关于将状态和行为保持在一起。数据隐藏意味着通过阻止直接访问内部状态来强制封装,因此客户端代码必须使用(公共)方法。这里的要点是1/允许对象保持一致状态(检查值,最终相应地更新状态的其他部分等),2/允许实现更改(内部状态/私有方法),而不破坏客户端代码。

像Java这样的语言对计算属性没有支持,因此在这种语言中保持封装的唯一方法是使所有属性受到保护或私有,并最终提供访问器。唉,有些人从来没有得到"最终"部分的权利,坚持为所有属性提供读/写访问器,这完全是胡说八道。

python通过描述符协议对计算属性有很强的支持(主要通过通用的property类型知道,但是您当然可以编写自己的描述符),因此不需要显式的getter/setter——如果您的设计要求某些类应该提供一个公共可访问的属性作为其API的一部分,那么可以总是从一个公共属性开始,如果在某个时刻需要更改实现,可以用计算属性替换它。

这并不意味着你应该公开你的所有属性!!!!-大多数情况下,您将拥有"实现属性"(支持内部状态的属性,但绝不是类API的一部分),并且您明确希望保护这些属性(通过在它们前面加上一个前导下划线)。

注意,python并没有试图在技术上强制保护隐私,它只是一种命名约定,您不能阻止客户机代码访问内部状态。这里没有什么好担心的,很少有人愚蠢到没有好的理由绕过官方的API,然后他们知道他们的代码可能会破坏某些东西并承担所有后果。