2016-11-13 2 views
0

рассмотрим следующий код:Использование метакласса для доступа к статическим атрибутам подкласса

def print_name(*args, **kwargs): 

    cls = type(*args, **kwargs) 
    print "hello " + cls.name 
    return type.__new__(*args, **kwargs) 

class B(object): 
    __metaclass__ = print_name 
    name = 'animal' 

class C(B): 
    name = "zebra" 

class D(B): 
    name = "pig" 

То, что я пытаюсь достичь имеют функцию print_name называться на B суб классов (C и D) и сделайте он печатает статический атрибут имя. Таким образом, желаемый результат должен выглядеть следующим образом:

animal 
zebra 
pig 

Спасибо!

ответ

2

В вашей print_name() функции, вы должны заменить это:

return type.__new__(*args, **kwargs) 

с этим:

return cls 

Таким образом, вы избавиться от TypeError вы видите.

Ошибка произошла потому, что первый аргумент __new__ должен быть объектом типа. Правильный вызов для __new__: type.__new__(type, *args, **kwargs), но в вашем случае нет необходимости создавать класс дважды.

Теперь даже с этим исправлением вы не увидите «зебра» и «свинья» на выходе, поскольку вы генерируете свой класс B непосредственно с type, чтобы ваша информация о метаклассе была потеряна.

Вы должны рассмотреть что-то вроде этого:

class print_name(type): 

    def __new__(mcls, *args, **kwargs): 
     cls = super(print_name, mcls).__new__(mcls, *args, **kwargs) 
     print "hello " + cls.name 
     return cls 

Таким образом, B и все его подклассы будут иметь тип print_name, и ваш код будет корректно выполняться каждый раз, когда создается подкласс.

(В качестве побочного примечания, метаклассы могут сделать невозможным использование множественного наследования, поэтому тщательно подумайте о том, действительно ли вы им нужны или нет.)

Смежные вопросы