我们知道,类实例化对象之后,会给对象的变量开辟一块内存,创建5个对象就要开辟5个内存空间,如果这些对象的变量的值是固定不变或者不经常变动,那么是不是可以给它们抽象出来,放在一个公共的区域,那么创建5个变量的时候,就只需要一份内存空间就可以.
__slots__的作用是为了节省存储空间,用在类中对某些经常被重复使用的变量进行固定的特殊处理,这种特殊处理是指,类实例化后的对象不能够再随意增加未定义的变量.只能有__slots__的列表中列出的变量.
1.使用__slots__之后,对象创建之后,就没有dict这个属性了,也就是变量不能够增加了,因为dict这个字典就是存放创建对象生成的变量.
class Person(object):
# __slots__ = ('name','age')
def __init__(self,name,age):
self.name = name
self.age = age
p = Person('张三', 18)
print(p.__dict__)
p.sex = '男'
print(p.__dict__)
运行结果:
{'name': '张三', 'age': 18}
{'name': '张三', 'age': 18, 'sex': '男'}
当使用__slots__之后,就会发现没有这个属性了,且不能够对对象进行随意增加未初始化定义的变量,如下:
class Person(object):
__slots__ = ('name','age')
def __init__(self,name,age):
self.name = name
self.age = age
p = Person('张三', 18)
print(p.__dict__)
p.sex = '男'
运行结果:
Traceback (most recent call last): File "C:/Users/10270/Desktop/py_test/test_10_6.py", line 26, inprint(p.__dict__) AttributeError: 'Person' object has no attribute '__dict__'
增加对象的属性sex时也是报错,如下:
class Person(object):
__slots__ = ('name','age')
def __init__(self,name,age):
self.name = name
self.age = age
p = Person('张三', 18)
# print(p.__dict__)
p.sex = '男'
运行结果:
Traceback (most recent call last): File "C:/Users/10270/Desktop/py_test/test_10_6.py", line 27, inp.sex = '男' AttributeError: 'Person' object has no attribute 'sex'
2.定义两个对象,如果它们的变量的值是一样的,则引用的是同一份数据,如果修改了其中了一个对象的一个变量值,那么不会修改另外一个对象的值,如下;
class Person(object):
__slots__ = ('name','age')
def __init__(self,name,age):
self.name = name
self.age = age
p1 = Person('张三', 18)
p2 = Person('张三', 18)
print(p1.name,p1.age,p2.name,p2.age)
print(id(p1.name),id(p2.name),id(p1.age),id(p2.age))
p2.name = '李四'
print(p1.name,p1.age,p2.name,p2.age)
print(id(p1.name),id(p2.name),id(p1.age),id(p2.age))
运行结果:
张三 18 张三 18 2180818556248 2180818556248 140727744357552 140727744357552 张三 18 李四 18 2180818556248 2180819715416 140727744357552 140727744357552
可以看到p2对象修改了name变量的值之后,不会修改P1的name的值,它们在内存中也不是引用同一个数据.
3.如果类中也声明了slots元组列表中的变量,那么此变量就变成了readonly,对象的变量和类变量就引用了同一个地址,修改类变量的值之后,对象的变量会一同被修改,后续的代码不能通过对象去修改这个变量的值,先看个例子,如下:
class Person(object):
__slots__ = ('name','age')
def __init__(self,name,age):
self.name = name
self.age = age
p1 = Person('张三', 18)
p2 = Person('张三', 18)
print(p1.name,p1.age,p2.name,p2.age)
print(id(p1.name),id(p2.name),id(p1.age),id(p2.age))
p2.name = '李四'
print(p1.name,p1.age,p2.name,p2.age)
print(id(p1.name),id(p2.name),id(p1.age),id(p2.age))
Person.name = '王老五' #类定义了同名的变量
p1.age = 3
p2.age = 4
print(p1.name,p1.age,p2.name,p2.age)#对象的同名变量值一同被修改,说明变量name已经和类绑定到一起了.
print("Person.name:",Person.name)
print(id(p1.name),id(p2.name),id(p1.age),id(p2.age))
print("id(Person.name):",id(Person.name))#name的引用和对象的引用一样
运行结果:
张三 18 张三 18 2681885971800 2681885971800 140727744357552 140727744357552 张三 18 李四 18 2681885971800 2681886082392 140727744357552 140727744357552 王老五 3 王老五 4 Person.name: 王老五 2681883872688 2681883872688 140727744357072 140727744357104 id(Person.name): 2681883872688
从上面可以看出,声明了同名的类变量之后,对象变量就是自动引用到这个类变量上,它们的id都是一样的.修改类变量的值,对象会一同被修改,牵一发而动全身.
此时如果使用对象去修改name的值,会报错,如下:
p1.name = '小明' #接上面的代码,增加这一行,运行结果会报错
运行结果:
Traceback (most recent call last): File "C:/Users/10270/Desktop/py_test/test_10_6.py", line 39, inp1.name = '小明' AttributeError: 'Person' object attribute 'name' is read-only



