十二. __slots__ 和 __dict__

十二. __slots__ 和 __dict__

1.__slots__

默认我们可以给class实例绑定任何属性和方法,这就是动态语言的灵活性如果我们想要限制class的属性怎么办?比如,只允许对Persion实例添加nameage属性。为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class能添加的属性

  • slots是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
class Str:
    # __slots__ = "name"
    # __slots__ = ["name","age"]
    __slots__ = ("name","age")  # 对象只拥有 name,age 属性
    
    def __init__(self,name,age):
        self.name = name
        self.age = age
        # self.sex = sex

p1 = Str("shawn",22)

print(p1.__slots__)      # ('name', 'age')
print(p1.name,p1.age)    # shawn 22

p1.friend = "水冰月"  # 报错 : "AttributeError" (friend没有放到slots中)

一旦在类中使用了 slots 属性, 实例出来的对象将不会有自己的 dict, 所有的对象,都共享使用类名称空间中的属性, 在此之前每生成一个对象, 都会申请一份内存空间, 对象越多, 占用的空间就越多, 使用了slots后, 对象越多,越节省内存

  • 共享类的名称空间属性示例
class Str:
    __slots__ = ["name","age"]

    def __init__(self,name,age):
        self.name = name
        self.age = age

p1 = Str("大雄",22)
p2 = Str("静香",90)

print(p1.name,p1.age)  # 大雄 22
print(p2.name,p2.age)  # 静香 90

print(p1.__slots__)    # ['name', 'age']
print(p2.__slots__)    # ['name', 'age']

print(p1.__dict__)     # 报错 : "AttributeError" 没有该属性
print(p1.__dict__)     # 报错 : "AttributeError" 没有该属性

print(Str.__dict__)
'''输出
{'__module__': '__main__', '__slots__': ['name', 'age'], '__init__': <function Str.__init__ at 0x0000025344BEC828>, \
'age': <member 'age' of 'Str' objects>, 'name': <member 'name' of 'Str' objects>, '__doc__': None}
'''
  • 当改变类的 name 和 age 时
Str.name = "小玉"
Str.age = 77

print(p1.name,p1.age)  # 小玉 77
print(p2.name,p2.age)  # 小玉 77
# 🔰发现所有对象的属性都发生了改变

总结 : 第一 : slots 属性是类属性, 可以用来限制实例对象能拥有的属性, 并且不再有自己的名称空间

第二 : 对象属性字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用slots取代实例的 dict

2.__dict__

  • dict 在前面的许多地方都使用到了 dict 这个属性, 它用来查看一个对象或类的名称空间属性,也可以说属性字典
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

P1 = Person("夏尔凡多姆海恩",1250)

print(P1.__dict__)  
# {'name': '夏尔凡多姆海恩', 'age': 1250}

print(Person.__dict__)
'''
{'__module__': '__main__', '__init__': <function Person.__init__ at 0x0000021CDDDAC4C8>, '__dict__': <attribute '__dict__' of 'Person' objects>,\
'__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
'''

posted @ 2021-01-05 22:20  给你骨质唱疏松  阅读(148)  评论(0)    收藏  举报