Я бы использовал inspect.ismemberdescriptor
в этом случае ( doc ):
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: Как отметил Аран-Фей в комментариях, это решение работает только в CPython.