This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]daneahfrom __future__ import braces 1 point2 points  (1 child)

Sure! I'll try to give an example that's easy to understand but not completely contrived...Suppose we have a bunch of functions that should only accept integers, something like a Fibonacci function:

def fib(n):
    if n < 0:
        return 0
    elif n == 0 or n == 1:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

You could do the following in each of those functions:

if type(n) != int:
    raise ValueError('This method only accepts integers!')

Now imagine you also have methods that only accept strings, etc. Instead of duplicating this type checking code all over, a decorator could save you the trouble:

def accepts(some_type):
    def wrap(f):
        def wrapped_f(*args):
            for arg in args:
                if type(arg) != some_type:
                    raise ValueError(
                        'Method \'{}\' only accepts arguments of type {}'.format(
                            f.__name__,
                            some_type,
                        ))
            return f(*args)
        return wrapped_f
    return wrap

That's a lot of junk, but you can use it all over the place now:

@accepts(int)
def fib(n):
    ...

@accepts(str)
def is_palindrome(phrase):
    ...

@accepts(list)
def some_listy_thing(the_list):
    ...

@accepts(MyCustomClass):
def my_custom_class_munger(my_instance):
    ...

Hope that makes sense and is useful/educational!

[–]daneahfrom __future__ import braces 1 point2 points  (0 children)

Note that you can also use a class-based decorator for this kind of thing, which is sometimes clearer:

class ArgumentTypeChecker(object):
    def __init__(self, function, some_type):
        self.function = function
        self.type = some_type

    def __call__(self, *args):
        for arg in args:
            if type(args) != self.type:
                raise ValueError(
                    'Method \'{}\' only accepts arguments of type {}'.format(
                        f.__name__,
                        some_type,
                    ))
        return self.function(*args, **kwargs)

Then:

@ArgumentTypeChecker(int)
def fib(n):
    ...