python - How can I give a function meta-data using decorators? -


based on this thread , have following

import functools def predicate(author, version, **others):     def _predicate(func):         @functools.wraps(func)         def wrapper(*args, **kwargs):             func.meta = {                 'author':  author,                 'version': version             }             func.meta.update(others)             func(*args, **kwargs)         return wrapper     return _predicate 

but unable simple use case of

@predicate('some author', 'some version') def second_of_two(a, b):     return b 

to work expected:

>>> second_of_two.meta['author'] 'some author' >>> second_of_two(1, 2) 2 

what doing wrong here?

you doing multiple things incorrectly, let’s see go through it:

in code, predicate generator decorator; actual decorator _predicate. decorators take function , return function; latter assigned original code added. @predicate(…) def second_of_two, name second_of_two value decorator returns.

so let’s see decorator does:

def _predicate(func):     @functools.wraps(func)     def wrapper(*args, **kwargs):         …     return wrapper 

it builds new internal function, uses functool.wraps (which practice), , returns function. far good; second_of_two gets decorated function correctly.

now, wrapper function though?

def wrapper(*args, **kwargs):     func.meta = {         'author':  author,         'version': version     }     func.meta.update(others)     func(*args, **kwargs) 

the wrapper function sets meta data on the original function object. that’s first mistake; set meta data on original function later isn’t referred again. second_of_two wrapper function, doesn’t have meta functions. in addition, set meta data when function runs. if set meta data correctly on wrapper function, still available once have called once. , third mistake call original function , throw away return value. that’s why didn’t output.

so should instead? first of all, set meta data outside of wrapper function, , set on function return. , inside wrapper function, return original function’s return value:

def predicate(author, version, **others):     def _predicate(func):         @functools.wraps(func)         def wrapper(*args, **kwargs):             return func(*args, **kwargs)          wrapper.meta = {             'author':  author,             'version': version         }         wrapper.meta.update(others)          return wrapper     return _predicate 

and now, wrapper function no longer special, can use original function instead:

def predicate(author, version, **others):     def _predicate(func):         func.meta = {             'author':  author,             'version': version         }         func.meta.update(others)         return func     return _predicate 

Comments

Popular posts from this blog

Android layout hidden on keyboard show -

google app engine - 403 Forbidden POST - Flask WTForms -

c - Why would PK11_GenerateRandom() return an error -8023? -