__slots__
,封装属性
__slots__
常见的的用法是用来封装属性,限制对实例胡乱添加属性。然而他还有一个重要的作用是可以减少内存使用。
当定义了__slots__
属性时,Python就会针对实例采用一种更加紧凑的内部表示。不在让每个实例都创建一个__dict__
字典,现在的实例是围绕着一个固定长度的小型数组来构建的,这和一个元组或者列表很相似。在__slots__
中列出的属性名会在内部映射到这个数组的特定索引上。使用__slots__
所带来的副作用是我们没法在对实例添加任何新的属性了——我们被限制在只允许使用__slots__
中列出的那些属性名。
class Date(object):
__slots__ = ['year', 'month', 'day']
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
d = Date('2017', '11', '21')
print(d.year+'-'+d.month+'-'+d.day)
#输出
2017-11-21
#设置属性hour
d.hour = '19'
#报错
AttributeError: 'Date' object has no attribute 'hour'
@property,创建可管理的属性
在对实例属性的获取和设定上,如果希望能够增加一些额外的处理过程(如类型检查或者验证),一种简单的方式是将其定义为property(也即把类中定义的函数当做一种属性来使用)。
class A(object):
def __init__(self, name):
self.name = name
# 将name定义为property属性,此处增加了增加了对name属性的修饰
@property
def name(self):
return 'my name is: ' + self._name
# 将可选方法setter绑定到name属性上,设定属性时做类型检查
@name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('Expect a string')
self._name = value
# 将可选方法deleter绑定到name属性上,此处设置为属性不可删除
@name.deleter
def name(self):
raise AttributeError('Cannot delet attribute!')
a = A('a')
a.name = 'shexuan'
print(a.name)
#输出
my name is: shexuan
#设置name属性为int(10)
a.name = 10
#报错
TypeError: Expect a string