1 __dict__
class Person(object):
is_alive = True
country = "China"
def __init__(self,name,age):
self.name = name
self.age = age
class Teacher(Person):
school = "哈佛"
def __init__(self,name,age,subject):
super().__init__(name,age)
self.subject = subject
teacher_jack = Teacher("jack",22,"math")
print(teacher_jack.__dict__) # {'name': 'jack', 'age': 22, 'subject': 'math'}
print(Teacher.__dict__) # {'__module__': '__main__', 'school': '哈佛', '__init__': <function Teacher.__init__ at 0x00671978>, '__doc__': None}
teacher_jack.__dict__["sex"] = "male" # 添加实例属性
print(teacher_jack.sex) # sex
del teacher_jack.__dict__
print(teacher_jack.__dict__["sex"]) # 删除实例属性
实例的__dict__是用来存储实例的属性,类的__dict__是用来存储类的属性和方法。并且类的__dict__不包含其父类的属性
2 dir()
class Person(object):
is_alive = True
country = "China"
def __init__(self,name,age):
self.name = name
self.age = age
class Teacher(Person):
school = "哈佛"
def __init__(self,name,age,subject):
super().__init__(name,age)
self.subject = subject
teacher_jack = Teacher("jack",22,"math")
print(dir(teacher_jack))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'age', 'country', 'is_alive', 'name', 'school', 'subject']
print(dir(Teacher))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'country', 'is_alive', 'school']
dir()函数返回的list中包含了对象的所有属性和方法,包含了从父类基础的属性。
3 __slots__
我们一般都是通过__dict__来存储实例的属性,还可以动态的添加和删除实例属性,那如果我们想固定实例的属性呢,不允许外部添加和删除实例属性,这时候就需要用__slots__
class Person(object):
__slots__ = ("name","age","sex")
country = "China"
def __init__(self,name,age):
self.name = name
self.age = age
jack = Person("jack",22)
# jack.__slots__ = ("name","age","sex","country") #__slots__属性只读,不能修改 抛出异常 AttributeError: 'Person' object attribute '__slots__' is read-only
# jack.is_alive = True # 给实例jack添加is_alive属性会抛出异常AttributeError: 'Person' object has no attribute 'is_alive'
# print(jack.sex) # 必须在__init__方法中对slots中的变量赋值(不能在外部对sex赋值),不然实例无法调用该属性,这里并未给sex赋值,抛出异常AttributeError: sex
# print(jack.__dict__) # 添加了__slots__后,实例就没有了__dict__属性,抛出异常'Person' object has no attribute '__dict__'
print(Person.__dict__) # 类还拥有__dict__,故可以给类添加,删除属性
Person.country = "中国" # 可以通过类来修改类变量
print(Person.country)
__dict__与__slots__的内存消耗
import tracemalloc
class Person1(object):
__slots__ = ("name","age","sex")
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# 跟踪内存消耗
p1 = Person1("jack",22,"male")
tracemalloc.start() # 开始跟踪内存分配
p = [Person1("jack",22,"male") for i in range(10000)]
snapshot = tracemalloc.take_snapshot() # 快照 当前内存分配
top = snapshot.statistics("filename") # 快照对象统计 监测文件
for start in top:
print(start)
# size=394 KiB, count=10001, average=40 B
import tracemalloc
class Person1(object):
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
# 跟踪内存消耗
p1 = Person1("jack",22,"male")
tracemalloc.start() # 开始跟踪内存分配
p = [Person1("jack",22,"male") for i in range(10000)]
snapshot = tracemalloc.take_snapshot() # 快照 当前内存分配
top = snapshot.statistics("filename") # 快照对象统计 监测文件
for start in top:
print(start)
# size=1019 KiB, count=29993, average=35 B
由上面的一个例子可以看出,__slots__比__dict__更节省内存