06.16 Python 中属性 Properties 和 Getters Setters 对比

Python 中属性 Properties 和 Getters Setters 对比

在许多面向对象的编程语言中,使用 Getters 和 Setters 确保数据的封装(data encapsulation)。他们使用公共的方法访问私有属性,这样私有属性就可以隐藏从而得到保护。

Getters 和 Setters


以下我们用 Java 式的写法写一个 Getters 和 Setters 的例子:

Python 中属性 Properties 和 Getters Setters 对比

输出:

Python 中属性 Properties 和 Getters Setters 对比

你会注意到,c2.set_x(c.get_x() + 3) 这样的写法很别扭,一点都不 Pythonic。

如果有一个公用的属性 x,可以直接:

Python 中属性 Properties 和 Getters Setters 对比

这样既容易编写代码,又有很好的可读性。

使用 Properties


我们重写一下刚才的类:

Python 中属性 Properties 和 Getters Setters 对比

这样是不是就非常简单了,但是,我们也丢失了数据封装。

假如我们限定 x 的取值只能是 0到100,不用 Getters 和 Setters 怎么实现呢?

Python 引入了属性 Property,请看使用 Property 的类:

Python 中属性 Properties 和 Getters Setters 对比

输出:

Python 中属性 Properties 和 Getters Setters 对比

使用 @property 装饰器装饰了一个获取属性值的方法。

另一个装饰器 @x.setter 装饰的是设置属性的方法上面。例如如果方法名是 y,就应该使用 @y.setter 装饰。

另外需要说明的是,在 __init__ 方法中,使用 self.x = x 同样调用了被装饰的方法,进行验证。

还有就是两个方法的名称相同,只是参数不同,分别是 def x(self)和 def x(self, x)。

不使用装饰器


可选的,不使用装饰器,Python 提供了另一种方法定义属性。

Python 中属性 Properties 和 Getters Setters 对比

使用 x = property(get_x, set_x) 就可以按照属性的方式访问。或者访问 set_x() 和 get_x() 方法。不过这样违背了 Python 的一个哲学(philosophy):应该始终只有一种优先的解决方案,能够很明显的处理它

即便使用这种方法能够解决问题,我们应该使用装饰器 @property。因为这样更 Pythonic。


分享到:


相關文章: