获取派生类的所有 __slots__

Posted

技术标签:

【中文标题】获取派生类的所有 __slots__【英文标题】:Get all __slots__ of derived class 【发布时间】:2011-10-06 22:30:18 【问题描述】:

我需要用 None 初始化实例的所有槽。如何获取派生类的所有槽?

示例(不起作用):

class A(object):
    __slots__ = "a"

    def __init__(self):
        # this does not work for inherited classes
        for slot in type(self).__slots__:
            setattr(self, slot, None)

class B(A):
    __slots__ = "b"

我可以使用一个额外的类属性来保存所有类的插槽(包括继承的),例如

class A(object):
    __slots__ = "a"
    all_slots = "a"

    def __init__(self):
        # this does not work for inherited classes
        for slot in type(self).all_slots:
            setattr(self, slot, None)

class B(A):
    __slots__ = "b"
    all_slots = ["a", "b"]

但这似乎不是最理想的。

感谢任何cmets!

干杯,

一月

【问题讨论】:

我使用这些类来处理客户端上的 JSON 业务项目(“标签”:richt 客户端、PyQt、通过描述符访问属性、延迟解析引用、类型验证)。我有多达一百万个这样的对象,所以内存需求可能是一个问题(即使我现在没有适当的真实世界数据——我知道你在想什么……万恶之源……;- ))。但我还需要禁止任何动态属性创建。这确保在将新创建的对象提交回服务器时没有“垃圾”属性。 【参考方案1】:

首先是

class A(object):
    __slots__ = ('a',)
class B(A):
    __slots__ =  ('b',)

创建一个包含 B 或其任何父类的 __slots__ 所包含的所有元素的列表将是:

from itertools import chain
slots = chain.from_iterable(getattr(cls, '__slots__', []) for cls in B.__mro__)

【讨论】:

谢谢!这很漂亮。我将第一次在我的代码中使用链! 这不太对。一个属性可能会出现在__slots__ 中的多个位置,例如在父母和孩子。因此,您生成的槽迭代器可以具有相同属性的多个副本。可能会做类似for cls in b.__class__.__mro__: slots.update(getattr(cls,"__slots__",[])) 之类的事情,其中​​槽是一些对象,例如集合。 建议将 getattr(cls, 'slots', []) 替换为 getattr(cls, 'slots', tuple() ) --由于 slots 倾向于用于许多非常小的对象,因此为 getattr 返回 [] 的少数情况创建额外列表的开销实际上可能很高(尽管创建 cls 缓存更好) 如果在同一属性的 mro 插槽中出现不止一次,这是一个代码错误并且应该修复 - OTH 可能值得麻烦先反转 mro 以获得超类插槽跨度> 【参考方案2】:

您想遍历MRO 中的每个类:

class A(object):
    __slots__ = ('x', 'y')
    def __init__(self):
        for slots in [getattr(cls, '__slots__', []) for cls in type(self).__mro__]:
            for attr in slots:
                setattr(self, attr, None)

您可以看到这在派生类中按预期工作:

class B(A):
    __slots__ = ('z',)

>>> b = B()

>>> b.x, b.y, b.z
<<< (None, None, None)

【讨论】:

感谢您的回答。 MRO 是缺失的部分。

以上是关于获取派生类的所有 __slots__的主要内容,如果未能解决你的问题,请参考以下文章

自定义 __repr__ 作为从 Enum 派生的类的类方法

C++_练习—继承_公有继承

派生类的类/元类方法装饰器

11).C#_所有类都派生自object类

类的派生

类的继承派生组合菱形的继承多态