Метапреимущества
Пакет gnosis.magic содержит несколько утилит для работы с метаклассами, а также некоторые примеры метаклассов, которые можно применять в аспектно-ориентированном программировании. Наиболее важная из этих утилит - import_with_metaclass(). Эта функция, задействованная в предыдущем примере, позволяет импортировать произвольный модуль, создавая все классы этого модуля с использованием метакласса, определенного пользователем, а не type. Какую бы новую возможность вы ни захотели задать в этом модуле, она может быть определена в метаклассе, который вы создаете (или получаете). gnosis.magic содержит некоторые подключаемые метаклассы сериализации; другой пакет мог бы включать возможности трассировки, объектную персистентность, регистрацию исключений или же что-нибудь еще.
Функция import_with_metaclass() иллюстрирует некоторые возможности программирования метаклассов:
Листинг 13. Функция import_with_metaclass() из [gnosis.magic]
def import_with_metaclass(modname, metaklass): "Module importer substituting custom metaclass" class Meta(object): __metaclass__ = metaklass dct = {'__module__':modname} mod = __import__(modname) for key, val in mod.__dict__.items(): if inspect.isclass(val): setattr(mod, key, type(key,(val,Meta),dct)) return mod
В этой функции стоит обратить внимание на стиль - обыкновенный класс Meta создан с использованием заданного метакласса. Но как только Meta добавлен в качестве предка, его потомки также создаются с помощью этого метакласса. В принципе, класс, подобный Meta, мог бы предоставлять и генератор метакласса, и ряд наследуемых методов - эти два аспекта наследования являются ортогональными.