python中__dict__,dir()和__slots__的区别

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__更节省内存

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值