__slots__ 和 __dict__

一、__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 = sexP1=Str("吉吉",8)
    print(P1.__slots__) #('name', 'age')
    print(P1.name,P1.age)   #吉吉 8P1.frind="淘小欣"      # 报错 : "AttributeError" (friend没有放到slots中)
    

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

  • 共享类的名称空间属性示例

    class Str:
        __slots__ = ["name", "age"]
    ​
        def __init__(self, name, age):
            self.name = name
            self.age = age
    ​
    ​
    P1 = Str("屁屁", 9)
    P2 = Str("皮皮", 8)
    print(P1.name, P1.age)  # 屁屁 9
    print(P2.name, P2.age)  # 皮皮 8print(P1.__slots__)  # ['name', 'age']
    print(P2.__slots__)  # ['name', 'age']print(P1.__dict__)     # 报错 : "AttributeError" 没有该属性
    print(P2.__dict__)     # 报错 : "AttributeError" 没有该属性print(Str.__dict__)
    '''输出内容
    {'__module__': '__main__', '__slots__': ['name', 'age'], '__init__': <function Str.__init__ at 0x000001AB93F6F040>, 'age': <member 'age' of 'Str' objects>, 'name': <member 'name' of 'Str' objects>, '__doc__': None}
    '''
    
  • 当改变类的 name 和 age 时

    Str.name = "小玉"
    Str.age = 77print(P1.name,P1.age)  # 小玉 77
    print(P2.name,P2.age)  # 小玉 77
    # 发现所有对象的属性都发生了改变
    

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

    第二 : 对象属性字典会占

二、__dict__

  • dict 在前面的许多地方都使用到了 dict 这个属性, 它用来查看一个对象或类的名称空间属性,也可以说属性字典

    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=ageP1=Person("淘小欣的开发之路",3342)
    print(P1.__dict__)      #{'name': '淘小欣的开发之路', 'age': 3342}print(Person.__dict__)
    ​
    '''输出内容
    {'__module__': '__main__', '__init__': <function Person.__init__ at 0x0000025C92CBB4C0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
    '''