为什么继承有__slots__属性的父类时,子类的实例化对象的属性会出现缺失
class D:__slots__ = ["x", "y"]
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class E(D):
pass
e = E(10, 15, 20)
e.__dict__
{'z': 20}
这里类E继承有__slots__属性的父类D时,子类E的实例化对象e的属性出现缺失
只有z, x和y消失了{:10_245:}
在Python中,使用__slots__属性可以限制类的实例对象只能具有特定的属性。当一个类定义了__slots__属性时,它告诉解释器该类的实例对象只能拥有__slots__属性中列出的属性,而不能拥有其他任意属性。
在你提供的示例代码中,父类D定义了__slots__ = ["x", "y"],这意味着D类的实例对象只能具有"x"和"y"这两个属性。然后,子类E继承了父类D但没有定义自己的__slots__属性。
当你创建子类E的实例对象e时,由于E类继承了D类的__slots__属性,解释器会按照__slots__属性中声明的属性名来分配内存空间。因此,e对象只能拥有"x"和"y"这两个属性,而无法直接访问或设置其他属性,如"z"。
所以,在你的示例中,当你创建了一个子类E的实例对象e,它只能拥有"x"和"y"这两个属性,而"z"属性只是传递给构造函数的参数,并不被保存在e对象中。这就解释了为什么e.__dict__的结果只包含"z"属性,而不包含"x"和"y"属性。
如果你想在子类E中拥有额外的属性,你可以在E类中定义它们的__slots__属性或将其声明为普通属性,这样就可以在实例化对象时进行设置。例如:
class E(D):
__slots__ = ["z"]
def __init__(self, x, y, z):
super().__init__(x, y)
self.z = z
e = E(10, 15, 20)
print(e.__dict__)# {'z': 20, 'x': 10, 'y': 15}
在这个示例中,子类E定义了自己的__slots__属性,并将"z"包括在内。然后在子类E的构造函数中,我们调用了父类D的构造函数并设置了"x"和"y"属性。接着,我们在子类E的构造函数中添加了设置"z"属性的代码。现在,创建子类E的实例对象e时,它将同时拥有"x"、"y"和"z"这三个属性。
希望这解答了你的疑问!如果还有其他问题,请随时提问。
如果问题已经解决,请设置最佳答案 在Python中,当一个类定义了 __slots__ 属性时,它限制了该类的实例只能具有 __slots__ 中列出的属性。这意味着,实例只能拥有 __slots__ 中指定的属性,而不能拥有其他属性。
在给定的代码中,父类D定义了 __slots__ 属性,包含了"x"和"y"两个属性。当子类E继承了父类D时,子类E的实例化对象e继承了父类D的 __slots__ 属性,并且只能具有"x"和"y"这两个属性。因此,当我们创建子类E的实例化对象e时,只有"x"和"y"这两个属性会被保留在实例的 __dict__ 属性中,而"z"这个属性并不在 __slots__ 中,所以它被忽略了。
这是 __slots__ 属性的一个特性,它可以用来限制实例的属性,从而减少内存消耗和提高访问速度。但需要注意的是,使用 __slots__ 属性时需要谨慎,因为它会限制实例的属性数量,并且只能在类的定义中使用,不能在实例化对象中动态添加新的属性。 本帖最后由 isdkz 于 2023-8-29 09:52 编辑
>>> D.__dict__
mappingproxy({'__module__': '__main__', '__slots__': ['x', 'y'], '__init__': <function D.__init__ at 0x000002172D4D5630>, 'x': <member 'x' of 'D' objects>, 'y': <member 'y' of 'D' objects>, '__doc__': None})
>>> E.__dict__
mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'E' objects>, '__weakref__': <attribute '__weakref__' of 'E' objects>, '__doc__': None})
x 和 y 都被 E 的父类的两个成员接管了,所以它不属于 e 对象独有的,自然就在 __dict__ 中看不到了
举个例子:
>>> class T:
... x = 1
... y = 1
... z = 1
...
>>> t = T()
>>> t.__dict__ # t 从它的类中获得的 x, y, z 并不属于它,所以 __dict__ 看不到
{}
>>> t.x = 18# 当 t 拥有了自己独有的成员对象, __dict__ 就可以看到
>>> t.__dict__
{'x': 18}
>>>
你之前的例子是因为从父类中继承过来的'x': <member 'x' of 'D' objects>, 'y': <member 'y' of 'D' objects>是一个独特的对象,当你给这个属性赋值的时候就会被这个成员对象拦截,所以子类是不可能拥有自己的x,y属性了,因为都被抢走了 isdkz 发表于 2023-8-29 09:30
>>> D.__dict__
mappingproxy({'__module__': '__main__', '__slots__': ['x', 'y'], '__init__': , 'x':...
明白了,谢谢啦{:5_108:}
页:
[1]