分享

十、Python property()函数:定义属性

 星光闪亮图书馆 2019-08-08
前面章节中,我们一直在用“类对象.属性”的方式访问类中定义的属性,其实这种做法是欠妥的,因为它破坏了类的封装原则。换句话说,正常情况下的类,它包含的属性应该是隐藏的,只允许通过类提供的方法来间接实现对类属性的访问和操作。

因此,在不破坏类封装原则的基础上,为了能够有效操作类中的属性,类中应包含读(或写)类属性的多个 getter(或 setter)方法,这样就可以通过“类对象.方法(参数)”的方式操作属性,例如:
  1. class Rectangle:

  2. # 定义构造方法

  3. def __init__(self, width, height):

  4. self.width = width

  5. self.height = height

  6. # 定义setsize()函数

  7. def setsize (self , size):

  8. self.width, self.height = size

  9. # 定义getsize()函数

  10. def getsize (self):

  11. return self.width, self.height

  12. # 定义delsize()函数

  13. def delsize (self):

  14. self.width, self.height = 0, 0

  15. rect = Rectangle(3 , 4)

  16. rect.setsize((6,8))

  17. print(rect.getsize())

运行结果为:

(6,8)


可能有读者觉得,这种操作类属性的方式比较麻烦,更习惯使用“类对象.属性”这种方式。庆幸的是,Python 中提供了 property() 函数,可以实现在不破坏类封装原则的前提下,让开发者依旧使用“类对象.属性”的方式操作类中的属性。

property() 函数的基本使用格式如下:

属性名=property(fget=None, fset=None, fdel=None, doc=None)

其中,fget 参数用于指定获取该属性值的类方法,fset 参数用于指定设置该属性值的方法,fdel 参数用于指定删除该属性值的方法,最后的 doc 是一个文档字符串,用于提供说明此函数的作用。

开发者调用 property() 函数时,可以传入 0 个(既不能读,也不能写的属性)、1 个(只读属性)、2 个(读写属性)、3 个(读写属性,也可删除)和 4 个(读写属性,也可删除,包含文档说明)参数。

例如,对前面的 Rectangle 类做适当的修改,使用 property() 函数定义一个 size 属性:
  1. class Rectangle:

  2. # 定义构造方法

  3. def __init__(self, width, height):

  4. self.width = width

  5. self.height = height

  6. # 定义setsize()函数

  7. def setsize (self , size):

  8. self.width, self.height = size

  9. # 定义getsize()函数

  10. def getsize (self):

  11. return self.width, self.height

  12. # 定义getsize()函数

  13. def delsize (self):

  14. self.width, self.height = 0, 0

  15. # 使用property定义属性

  16. size = property(getsize, setsize, delsize, '用于描述矩形大小的属性')

  17. # 访问size属性的说明文档

  18. print(Rectangle.size.__doc__)

  19. # 通过内置的help()函数查看Rectangle.size的说明文档

  20. help(Rectangle.size)

  21. rect = Rectangle(4, 3)

  22. # 访问rect的size属性

  23. print(rect.size) # (4, 3)

  24. # 对rect的size属性赋值

  25. rect.size = 9, 7

  26. # 访问rect的width、height实例变量

  27. print(rect.width) # 9

  28. print(rect.height) # 7

  29. # 删除rect的size属性

  30. del rect.size

  31. # 访问rect的width、height实例变量

  32. print(rect.width) # 0

  33. print(rect.height) # 0

程序中,使用 property() 函数定义了一个 size 属性,在定义该属性时一共传入了 4 个参数,这意味着该属性可读、可写、可删除,也有说明文档。所以,该程序尝试对 Rectangle 对象的 size 属性进行读、写、删除操作,其实这种读、写、删除操作分别被委托给 getsize()、setsize() 和 delsize() 方法来实现。

运行上面程序,将会看到如下输出结果:

用于描述矩形大小的属性
Help on property:

    用于描述矩形大小的属性

(4, 3)
9
7
0
0


在使用 property() 函数定义属性时,也可根据需要只传入少量的参数。例如,如下代码使用 property() 函数定义了一个读写属性,该属性不能删除:
  1. class User :

  2. def __init__ (self, first, last):

  3. self.first = first

  4. self.last = last

  5. def getfullname(self):

  6. return self.first + ',' + self.last

  7. def setfullname(self, fullname):

  8. first_last = fullname.rsplit(',');

  9. self.first = first_last[0]

  10. self.last = first_last[1]

  11. # 使用property()函数定义fullname属性,只传入2个参数

  12. # 该属性是一个读写属性,但不能删除

  13. fullname = property(getfullname, setfullname)

  14. u = User('悟空', '孙')

  15. # 访问fullname属性

  16. print(u.fullname)

  17. # 对fullname属性赋值

  18. u.fullname = '八戒,朱'

  19. print(u.first)

  20. print(u.last)

此程序中使用 property() 定义了 fullname 属性,该程序使用 property() 函数时只传入两个参数,分别作为 getter 和 setter方法,因此该属性是一个读写属性,不能删除。

运行上面程序,将看到如下输出结果:

悟空,孙
八戒

在某些编程语言中,类似于这种 property() 函数合成的属性被称为计算属性。这种属性并不真正存储任何状态,它的值其实是通过某种算法计算得到的。当程序对该属性赋值时,被赋的值也会被存储到其他实例变量中。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多