Метаклассы python на уровне модуля
Я читаю Что такое метакласс в Python?
и я попытался воспроизвести верхний метакласс из примера и обнаружил, что это не работает во всех случаях:
def upper(cls_name, cls_parents, cls_attr):
""" Make all class attributes uppper case """
attrs = ((name, value) for name, value in cls_attr.items()
if not name.startswith('__'))
upper_atts = dict((name.upper(), value) for name, value in attrs)
return type(cls_name, cls_parents, upper_atts)
__metaclass__ = upper #Module level
class Foo:
bar = 1
f = Foo()
print(f.BAR) #works in python2.6
Вышеупомянутый сбой (с ошибкой атрибута) в python3, который я считаю естественным, потому что все классы в python3 уже имеют объект, поскольку их родительское и метаклассовое разрешение попадают в класс объекта.
Вопрос:
Как создать метакласс уровня модуля в python3?
Ответы
Ответ 1
Метакласс уровня модуля на самом деле не является "уровнем модуля", он связан с тем, как работает инициализация класса. Создание класса будет искать переменную "__metaclass__"
при создании класса, и если бы она не была в локальной среде, она бы выглядела в глобальном. Следовательно, если бы у вас был "уровень модуля" __metaclass__
, который будет использоваться для каждого класса после этого, если у них не было явных метаклассов.
В Python 3 вместо этого вы определяете метакласс с metaclass=
в определении класса. Следовательно, метаклассы уровня модуля отсутствуют.
Итак, что вы делаете? Легко: Вы указываете его явно для каждого класса.
Это действительно не так много дополнительной работы, и вы даже можете сделать это с хорошим поиском regexp и заменить, если у вас действительно есть сотни классов и вы не хотите делать это вручную.
Ответ 2
Если вы хотите изменить все атрибуты в верхнем регистре, вы, вероятно, должны использовать метод __init__
, чтобы сделать это, чем использовать метакласс.
Метаклассы более глубокие, чем 99% пользователей должны когда-либо беспокоиться. Если вы задаетесь вопросом, нужны ли вам они, вы не делаете (люди, которые действительно нуждаются в них, знают с уверенностью, что они в них нуждаются, и не нуждаются в объяснении о том, почему).
- Python Guru Тим Питерс
Если вам нужно что-то более глубокое, вы также должны оценить с помощью Class Decorators.
Использование MetaClasses и понимание того, как создаются классы, настолько ненужны, пока вы хотите сделать что-то, что вы можете сделать, используя декораторы классов или инициализацию.
Тем не менее, если вы действительно хотите использовать Metaclass tho 'pass, что в качестве аргумента ключевого слова для класса.
class Foo(object, metaclass=UpperCaseMetaClass)
где UpperCaseMetaClass
- класс, который расширяет type
, а не метод.
class UpperCaseMetaClass(type):
def __new__():
#Do your Magic here.