문제

I wanted to make it easier to register callbacks using decorators when designing a library, but the problem is that they both use the same instance of the Consumer.

I am trying to allow both these examples to co-exist in the same project.

class SimpleConsumer(Consumer):
     @Consumer.register_callback
     def callback(self, body)
         print body

class AdvancedConsumer(Consumer):
     @Consumer.register_callback
     def callback(self, body)
         print body

a = AdvancedConsumer()
s = SimpleConsumer()

What happens here is that the callback implementation of AdvancedConsumer will override the one of the SimpleConsumer, as it is defined last.

The implementation of the decorator class is pretty simple.

class Consumer(object):
      def start_consumer(self):
            self.consuming_messages(callback=self._callback)

       @classmethod
       def register_callback(cls, function):        
           def callback_function(cls, body):
               function(cls, body)

           cls._callback = callback_function
           return callback_function

I am very happy with the implementation, but as there is a possibility that someone will register a second callback I would like to ensure that it won't be a problem in the future. So, does anyone have a suggestion on how to implement this in a way that is not static?

The implementation shown here is obviously simplified, and as a precaution I have something like this in the code.

if cls._callback:
    raise RuntimeError('_callback method already defined')
도움이 되었습니까?

해결책

You can do it with a class decorator:

def register_callback(name):
    def decorator(cls):
        cls._callback = getattr(cls, name)
        return cls
    return decorator

@register_callback('my_func')
class SimpleConsumer(Consumer):
     def my_func(self, body):
         print body

If you want to decorate a method, you will get only a function in it so you cannot access any information about the class that the method is contained in.

But if only one callback should be available per class why just not call it _callback?

class SimpleConsumer(Consumer):
     def _callback(self, body):
         print body

Or do something like:

class SimpleConsumer(Consumer):
     def my_func(self, body):
         print body

     _callback = my_func

?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top