In [39]:
from functools import partial

a = 5

class inject(object):
    def __init__(self, *args, **kwargs):
        print "inject() invoked"
        self.args = args
        self.kwargs = kwargs
        
    def __call__(self, f):
        args, kwargs = self.args, self.kwargs
        f(5) #(*args, **kwargs)
        
@inject(a=9)
def print_a(a):
    print a
print_a()


inject() invoked
5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-39-c7b90c1bdd20> in <module>()
     16 def print_a(a):
     17     print a
---> 18 print_a()

TypeError: 'NoneType' object is not callable

In [49]:
class decoratorWithArguments(object):

    def __init__(self, arg1, arg2, a4=None):
        """
        If there are decorator arguments, the function
        to be decorated is not passed to the constructor!
        """
        print "Inside __init__()"
        self.arg1 = arg1
        self.arg2 = arg2
        self.a4 = a4

    def __call__(self, f):
        """
        If there are decorator arguments, __call__() is only called
        once, as part of the decoration process! You can only give
        it a single argument, which is the function object.
        """
        print "Inside __call__()"
        def wrapped_f(*args):
            print "Inside wrapped_f()"
            f(self.arg1, self.arg2, a4=self.a4, *args)
            print "After f(*args)"
        return wrapped_f

@decoratorWithArguments("hello", "world", a4=42)
def sayHello(a1, a2, a4=None):
    print 'sayHello arguments:', a1, a2, a4
    
sayHello("Vasya")


 Inside __init__()
Inside __call__()
Inside wrapped_f()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-49-2984ff328e7b> in <module>()
     28     print 'sayHello arguments:', a1, a2, a4
     29 
---> 30 sayHello("Vasya")

<ipython-input-49-2984ff328e7b> in wrapped_f(*args)
     20         def wrapped_f(*args):
     21             print "Inside wrapped_f()"
---> 22             f(self.arg1, self.arg2, a4=self.a4, *args)
     23             print "After f(*args)"
     24         return wrapped_f

TypeError: sayHello() got multiple values for keyword argument 'a4'

In [ ]: