2013-12-13 4 views
3

Я пытаюсь сделать это:Python декоратора для класса

import unittest 

def decorator(cls): 
    class Decorator(cls): 
     def __init__(self, *args, **kwargs): 
      super(Decorator, self).__init__(*args, **kwargs) 

    return Decorator 

@decorator 
class myClass(unittest.TestCase): 
    def __init__(self, *args, **kwargs): 
     super(myClass, self).__init__(*args, **kwargs) 
     self.test = 'test' 

    def test_test(self): 
     pass 


myClass().run() 

Но я получаю рекурсии в MyClass.__init__. Есть ли способы избежать этого?

+2

Подсказка к OP: Если вы вставляете здесь уменьшенный код, убедитесь, что он действительно показывает проблему, которую вы собираетесь решить. В этом случае просто вставьте опубликованный код в интерактивный Python и попробуйте его. – Alfe

+0

Я обновил свой код до проблемной версии. – Eugene

+1

Что это за 'декоратор ', который должен выполняться в роли« декоратора класса »... –

ответ

7

Вы не можете использовать super(myClass, self) в оформленном классе таким образом.

myClass ищется как глобальный, а глобальная myClass является отскока в Decorator, так что вы говорите Python искать в классе MRO для __init__ начиная с Decorator, который myClass, который вызывает super(myClass, self).__init__(), глядя вверх myClass как глобальный, который связан с Decorator и т.д.

Самый простой обходной не использовать super() здесь:

@decorator 
class myClass(unittest.TestCase): 
    def __init__(self, *args, **kwargs): 
     unittest.TestCase.__init__(self, *args, **kwargs) 
     self.test = 'test' 

Это одна из причин, почему в Python 3 была введена версия без аргумента super(), дающая методы вместо __class__.

Вы могли прыгать через некоторые (очень сложно) обручи, чтобы пересобрать метод myClass.__init__(), чтобы дать ему myClass замыкания, связанное с исходным объектом неукрашенного класса вместо этого, но для UnitTest, я бы не стал заморачиваться.