2013-07-05 2 views
2

Возможно ли каким-либо образом настроить модуль python или REPL для использования метакласса по умолчанию для всех классов, независимо от того, используется ли метакласс в классе?Python default metaclasses

class met(type): 
    def __init__(cls, name, bases, dct): 
     super(met, cls).__init__(name, bases, dct) 
     setattr(cls, "_test_member", "test_value") 

class A(object): 
    pass 

>>> A._test_member 
'test_value' 

ответ

3

Использование (теперь удален) комментарий Павла Anossov в:

class met(type): 
    def __init__(cls, name, bases, dct): 
     super(met, cls).__init__(name, bases, dct) 
     cls._test_member = "test_value" 

object = met('object', (object,), {}) 

class A(object): 
    pass 

print(A._test_member) 

печатает

test_value 

Обратите внимание, что класс может иметь только один метакласса. (Так как, в конце концов, любой объект может иметь только один тип). Но, кроме того, метакласс класса должен быть (нестрогим) подклассом метаклассов всех его оснований. Другими словами, метакласс класса и метаклассы всех его баз либо должны быть одинаковыми, либо все эти метаклассы должны быть подклассами друг друга. Таким образом, вышеупомянутое решение может не работать, если класс пытается использовать метакласс, который не является подклассом met.

Например,

class met(type): 
    def __init__(cls, name, bases, dct): 
     super(met, cls).__init__(name, bases, dct) 
     cls._test_member = "test_value" 

object = met('object', (object,), {}) 

class someothertype(type): pass 

class B(object): 
    __metaclass__ = someothertype 

поднимает

TypeError: Error when calling the metaclass bases 
    metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases 
+0

Я не знал, что вы можете переопределить объект, используя его в качестве базы. Очень подлый. – dilbert

+0

@PavelAnossov: Если вы хотите опубликовать ответ, я удалю его. – unutbu

+0

@unutbu: Я заменил 'setattr (cls," _test_member "," test_value ")' с его более обычной и прямой формой. – EOL

2

На Python 2.x вы можете просто сделать

__metaclass__ = met 

в начале модуля, а затем определить свой класс в старом режиме стиля:

class A: 
    pass 

На 3.x , это уже невозможно. Кроме того, «Явный лучше, чем неявный».

Другой подход, вы можете сделать:

class Object(metaclass=met): # Py3k syntax 
    pass 

и всегда наследуют от него.

Примечание: вызов подкласса type - это единственный способ использования метакласса, совместимого как с Py2k, так и с Py3k. Как и в ответ unutbu «s

+0

Есть ли способ, чтобы переопределить встроенный класс объекта использовать метакласса? – dilbert

+0

вы можете переподтвердить его, как сказано в комментарии выше: 'object = Object' – JBernardo

+1

Это было бы невероятно опасно, подвержено ошибкам и вообще нежелательно. – user2357112

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

  • Нет связанных вопросов^_^