有没有一种可靠的方法来列出类的所有__slots__?

时间:2019-06-21 09:15:44

标签: python attributes slots

我正在寻找一种方法来可靠地使用__slots__获取类的所有插槽名称的列表。示例:

class A:
    __slots__ = ('a',)

print(list_slots(A))  # should output ['a']

当然,list(A.__slots__)可以完成此操作,但是不幸的是,有几件事情使这变得更加困难:

  • 继承的广告位:

    class B(A):
        __slots__ = ('b',)
    
    print(list_slots(B))  # should output ['a', 'b']
    
  • 字符串:

    class C:
        __slots__ = 'xyz'
    
    print(list_slots(C))  # should output ['xyz']
    
  • 迭代器:

    class D:
        __slots__ = iter(['d'])
    
    print(list_slots(D))  # should output ['d']
    

如您所见,这里有很多陷阱... list_slots的实现是否可以正确处理所有这些情况?

1 个答案:

答案 0 :(得分:0)

在这种情况下,我会使用inspect.ismemberdescriptordoc):

import inspect

class A:
    __slots__ = ('a',)

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

class X(B):
    __slots__ = ('c',)

class C:
    __slots__ = 'xyz'

class D:
    __slots__ = iter(['d'])

def get_slots(cls):
    for k, v in cls.__dict__.items():
        if inspect.ismemberdescriptor(v):
            yield k
    for b in cls.__bases__:
        yield from get_slots(b)

print(list(get_slots(A)))
print(list(get_slots(B)))
print(list(get_slots(C)))
print(list(get_slots(D)))
print(list(get_slots(X)))

打印:

['a']
['b', 'a']
['xyz']
['d']
['c', 'b', 'a']

编辑1:更新了我对get_slots()递归版本的回答

编辑2:正如Aran-Fey在评论中指出的那样,该解决方案仅在CPython中有效。