当用property装饰一个属性,并且这个属性返回的是一个list(或者一个类,一个dict,都会有同样的情况),那么如果我们使用list的索引去访问list,setter将不起任何作用。
如下所示:
In [1]: class test(object):
...: a = [10,10,10]
...: @property
...: def ads(self):
...: print 'get'
...: return self.a
...: @ads.setter
...: def ads(self, val):
...: print 'set'
...: self.a = val
...:
In [2]: test = test()
In [3]: test.ads[1] = 1
get
In [4]: test.ads
get
可以看到,全程并没有运行setter(输出没有出现过“set”),而property的值却被改变了。
如果想要防止这种情况的发生,应该对property的值加以判断,如果不是基础类型,就使用深拷贝,能够避免这种情况的发生。
例如:
In [1]: def is_container(val):
...: '''判断一个变量是否为基本的类型,如果是,就意味着可以直接不需要拷贝赋值'''
...: return not type(val) in (int, float, long, complex, str)
...:
In [2]: import copy
...: class test(object):
...: a = [10,10,10]
...: @property
...: def ads(self):
...: print 'get'
...: if not is_container(self.a):
...: return self.a
...: else:
...: return copy.deepcopy(self.a)
...: @ads.setter
...: def ads(self, val):
...: print 'set'
...: self.a = val
...:
In [3]: test = test()
In [4]: test.ads[1] = 1
get
In [5]: test.ads
get
Out[5]: [10, 10, 10]