Для библиотеки вкладок Django я создал архитектуру, которая использует отслеживание отмеченных подклассов.Отслеживание подкласса Python - метаклассы vs Builtin
Для этого я создал базовый класс, а затем вывел из него все классы вкладок. Я отслеживаю классы потомков, используя функцию, которая рекурсивно использует метод cls.__subclasses__()
.
Чтобы узнать, какие подклассы являются классами листьев/реальными вкладками, я решил сделать это вручную, добавив __tab__ = True
в любой класс, который я хочу отобразить как вкладку. Причина этого в том, что я создаю другие классы абстракции ниже TabView
, которые не должны отображаться в виде вкладок. Возможно, это может быть переписано в качестве декоратора.
Пример:
def get_descendants(cls):
"""Returns all subclasses for cls, and their sublasses, and so on..."""
descendants = []
subclasses = cls.__subclasses__()
for subclass in subclasses:
descendants.append(subclass)
descendants += get_descendants(subclass)
return descendants
def TabView(object):
def _tab_group_members(self):
descendants = get_descendants(TabView)
return [d for d in descendants if '__tab__' in d.__dict__]
(...)
def ConcreteTab(TabView):
__tab__ = True
Сейчас я начал читать "Про Джанго" книги Marty Alchin в. Там, он предлагает использование метаклассов для отслеживания подклассов:
class SubclassTracker(type):
def __init__(cls, name, bases, attrs):
try:
if TrackedClass not in bases:
return
except NameError:
return
TrackedClass._registry.append(cls)
class TrackedClass(object):
__metaclass__ = SubclassTracker
_registry = []
Каковы преимущества метакласса подхода? Это лучше, чем использование __subclasses__()
?
Никогда не изобретайте имена '__foo__'. – yak
@yak спасибо за комментарий. так что '_tab' будет лучше? или '_tab_'? (в любом случае, я заменил бы его декоратором). –