views:

113

answers:

1

Are the comments in the following code correct? Particularly the "instance =..." one?

# This does nothing.

class donothing(object):
    def __init__(self, func):
        """
        The 'func' argument is the function being decorated because in this
        case, we're not instantiating the decorator class. Instead we are just
        using the class object as a callable (a class is always callable as this
        is how an instance is returned) to use as a decorator, which means that
        it is being instantiated upon definition of the decorated function and
        the decorated function is being passed in as an argument to the class's
        __init__ method.
        """
        self.func = func

    def __call__(self, *args, **kwargs):
        """
        The __call__ function is called when the decorated function is called
        because the function has be eaten by the decorator class. Now it's up to
        the this method to return a call to the original function. The arguments
        are passed in as args, kwargs to be manipulated.
        """
        # Returns original function call with original arguments.
        return self.func(*args, **kwargs)

@donothing
def printer(text):
    print(text)

printer('hello world')

# The printer function is now an alias for the donothing instance created, so
# the preceding was the same as:
#
# instance = donothing(printer)
# instance('hello world')
#


# Next example:

class checkforkeysinparams(object):
    def __init__(self, required):
        self.required = set(required)

    def __call__(self, params):
        def wrapper(params):
            missing = self.required.difference(params)
            if missing:
                raise TypeError('Missing from "params" argument: %s' % ', '.join(sorted(missing)))
        return wrapper


# Apply decorator class, passing in the __init__'s 'required' argument.

@checkforkeysinparams(['name', 'pass', 'code'])
def complex_function(params):
    # Obviously these three are needed or a KeyError will be raised.
    print(params['name'])
    print(params['pass'])
    print(params['code'])


# Create params to pass in. Note, I've commented out one of the required params.

params = {
    'name': 'John Doe',
    'pass': 'OpenSesame',
    #'code': '1134',
}

# This call will output: TypeError: Missing from "params" argument: code

complex_function(params=params)
+1  A: 

Yes perfect description, decorator donothing decorates the function printer and returns a object of class donothing, so yes decorator simply boils down to this

x = donothing(func) # donothing is a class not function

and you can use it like this, if you wish to avoid @deco syntax.

so now x is an object, when you do x(), __call__ of that object is called and there it calls the function which was passed in __init__

edit: Second decorator is wrong , because it only checks the parameter but never calls the function being passed and function being passed to decorator is names params but should be name something like func or better name

you can test that it does nothing by passing correct params

params = {
    'name': 'John Doe',
    'pass': 'OpenSesame',
    'code': '1134',
}
complex_function(params=params)

it doesn't print the arguments as complex_function is supposed to do.

so correct decorator is

class checkforkeysinparams(object):
    def __init__(self, required):
        self.required = set(required)

    def __call__(self, func):
        def wrapper(params):
            missing = self.required.difference(params)
            if missing:
                raise TypeError('Missing from "params" argument: %s' % ', '.join(sorted(missing)))

            func(params)

        return wrapper

In first example Class is being used as decorator itself, here the object of class checkforkeysinparams is used as deocrator hence function gets passed to __call__ of that object

Anurag Uniyal
Sweet thx for clarifying, BTW, I love the @ syntax. And what about the second one.
orokusaki
@orokusaki, I added explanation of second decorator, which btw is wrongly coded
Anurag Uniyal
Oh, sweet thanks Anurag.
orokusaki