Python中特性和属性的理解

最近阅读《Python基础教程(第二版)》一书,在<第九章:属性>——属性一节中,出现了特性和属性的介绍,但是很乱,让人看不懂。
于是我查阅了一些网络资料,并且反复阅读这一章节多次后,有了一些心得体会,放在下方供大家查阅:

  • 首先是查阅资料,有一篇介绍python特性的文章讲解的很不错,我拿来共享

特性是对类的一个特定属性的操作进行拦截,在操作这个属性时,执行特定的函数,对属性的操作进行拦截。

  • 在反复阅读<第九章:属性>——属性一节后,我先修改书中一些字词,方便大家理解(修改之处我会用黑体标明)

属性

第7章曾经提过访问器方法。访问器是一个简单的方法,它能够使用getHeight、setHeight这样的名字来得到(getHeight)或者重绑定(setHeight)一些特性(这里的特性是指在__init__中初始化的一些变量:self.name = 'ZhangSan')或者属性可能是类的私有属性(这里的属性是指类本身的一些性质)——具体内容请参见第7章的“再论私有化”部分)。将状态变量(特性)封装起来,然后让访问者通过封装的方法(或者函数)进行访问,是很重要的一件事。比如下面例子中的Rectangle类:

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0
    def setSize(self, size):
        self.width, self.height = size
    def getSize(self):
        return self.width, self.height

下面的例子演示如何使用这个类:

>>> r = Rectangle()   #这里实例化
>>> r.width = 10    
>>> r.height = 5
>>> r.getSize()  #可以得到width和height特性
(10, 5)
>>> r.setSize((150, 100))   #将width=150和height=100特性通过setSize封装起来,然后可供getSize函数进行访问。
>>> r.width  #这里就是访问实例的width特性
150

在上面的例子中,getSize和setSize方法是设想在实例中存在名为size特性的访问器方法(其实在上例中并不存在size特性),size由width和height构成的元组。读者可以随意使用一些更有趣的方法替换这里的函数,例如计算面积或者对角线的长度。这些代码(getSize和setSize方法)没错,但有缺陷——当程序员去使用这个类时,不应该还要思考它是怎么实现封装的。
如果有一天改变了类的实现——将size变成一个真正的特性,这样width和height就可以使用r.size来展示——那么就要把它们放到一个访问器方法中,并且任何调用了这个类的程序都必须重写调用方法(将r.getSize()r.setSize()重写为r.sizer.size = (150, 100)),客户代码应该能够用同样的方式去访问所有特性。
如何实现上面说的将size变成一个真正的特性呢?将元类代码中所有的属性都放到访问器中?这样子当然没问题,但如果有很多简单的特性要去访问(例如面积和对角线的长度等等...),那么就很笨了,需要写很多访问器才行,它们除了返回(getSize)或者重新绑定(setSize)之外不做任何事,这样不管是尺寸、面积、对角线长度等等特性,都需要写两个访问器方法(get和set)。这样就很繁琐了(不管调用尺寸、面积、对角线长度等,都需要get+尺寸/面积/对角线长度这样的方法,如果能只是用尺寸/面积/对角线长度这样简单的的方法来进行该有多好),复制加粘贴式或切割代码式的编程方式显然是很糟糕的(尽管是在一些语言中针对这样的特殊问题很普遍)。幸好,Python能隐藏访问器方法(r.sizer.size = (150, 100)都没有显示出访问器方法,但是都有相同的作用,这就是隐藏的好处),让所有特性看起来一样(r.sizer.size = (150, 100)r.arear.area = 600r.diagonalr.diagonal = 80这些特性看起来没什么差别)。以上这些被访问器定义的特性(self.width和self.height)称为属性。(这里我理解为属性就是被访问器定义的self.width和self.height,而特性就是对属性(self.width和self.height)进行“getSize”和“setSize”的操作的拦截(将以上两个操作,通过size = property(getSize, setSize)拦截后,size就是特性(这里也可以理解为拦截后具有的独特性质size)))

这里图示说明一下:
属性(self.width和self.height) -----> 访问器方法(getSize和setSize方法) -----> 拦截函数(size = property(getSize, setSize) -----> 特性size出现

书的最后说然后我会简单地说明一下如何使用特殊方法实现属性(这里应该是**特性**)
最后,如果还不明白特性和属性之间的区别,就这样想(他俩没实例化都叫做属性,实例化后都叫做特性)

Ps:以上纯属个人拙见,不当之处还望不吝赐教!

你可能感兴趣的:(Python中特性和属性的理解)