__slots__属性总结
*特点:
使用 slots 的注意事项
当继承自一个未定义 slots 的类时,实例的 dict 和 weakref 属性将总是可访问。
没有 dict 变量,实例就不能给未在 slots 定义中列出的新变量赋值。尝试给一个未列出的变量名赋值将引发 AttributeError。新变量需要动态赋值,就要将 ‘dict’ 加入到 slots 声明的字符串序列中。
如果未给每个实例设置 weakref 变量,定义了 slots 的类就不支持对其实际的弱引用。如果需要弱引用支持,就要将 ‘weakref’ 加入到 slots 声明的字符串序列中。
slots 是通过为每个变量名创建描述器 (实现描述器) 在类层级上实现的。因此,类属性不能被用来为通过 slots 定义的实例变量设置默认值;否则,类属性就会覆盖描述器赋值。
slots 声明的作用不只限于定义它的类。在父类中声明的 slots 在其子类中同样可用。不过,子类将会获得 dict 和 weakref 除非它们也定义了 slots (其中应该仅包含对任何 额外 名称的声明位置)。
如果一个类定义的位置在某个基类中也有定义,则由基类位置定义的实例变量将不可访问(除非通过直接从基类获取其描述器的方式)。这会使得程序的含义变成未定义。未来可能会添加一个防止此情况的检查。
非空的 slots 不适用于派生自“可变长度”内置类型例如 int、bytes 和 tuple 的派生类。
任何非字符串可迭代对象都可以被赋值给 slots。映射也可以被使用;不过,未来可能会分别赋给每个键具有特殊含义的值。
class 赋值仅在两个类具有相同的 slots 时才会起作用。
带有多个父类声明位置的多重继承也是可用的,但仅允许一个父类具有由声明位置创建的属性(其他基类必须具有空的位置布局) —— 违反规则将引发 TypeError。
如果为 slots 使用了一个迭代器,则会为迭代器的每个值创建描述器。 但是 slots 属性将为一个空迭代器。*
举例说明:
#给类添加__slots__属性实现在只有__slots__变量中的实行才能被添加,没有在__slots__变量中的属性会添加失败。可以防止其他人在调用类的时候胡乱添加属性或方法。
#__slots__属性子类不会继承,只有在当前类中有效
class Student(object):
__slots__ = ('name','age')
#以字符串的形式添加属性 'score' 使用该方法可以节约内存空间
def __str__(self):
return '{}...{}'.format(self.name,self.age)
pass
# zs=Student('张三',19)
zs=Student()
zs.name='张三'
zs.age=19
# zs.score=100 #因为在__slots__里面没有score属性,所以动态添加后还是不能访问
# print(zs.__dict__) #所有可以用到的属性都在这里存储,不足的地方是占用的内存空间较大
print(zs)
#子类未声明__solts__时,那么是不会继承父类的__solts__的,此时的子类是可以随意的属性赋值的
class subStudent(Student):
# __slots__ = ('gender','job') 如果声明了__solts__,那么就会继承父类的__solts__ 里面限定的属性尽量不要跟父类的重复,因为会消耗内存空间
pass
ln=subStudent()
ln.gender='男'
ln.job='计算机科学'
print(ln.gender,ln.job)
结果: