How do attributes on functions withstand wrapping?

Let's say I have the following function that has an attribute that marks it for special processing in the callback subsystem:

def my_func(msg):
    print msg

my_func.my_marker = SPECIAL_CONSTANT

The problem is that if other bits of the code are completed my_funcusing functools.partialor another decorator, then it my_markerwill be lost.

my_partial = partial(my_func, 'hello world')
print my_partial.my_marker
>>> AttributeError...

Is there a way to protect function attributes when packaging? Is there a better way to store metadata currently stored in my_marker? It seems that keeping the reference to the original function is suffering from the same problem.

+1
source share
3 answers

, , , , func.

. .

from functools import partial

SPECIAL_CONSTANT = 'bam'


def my_func(msg):
    print msg

my_func.my_marker = SPECIAL_CONSTANT

my_partial = partial(my_func, 'hello world')

print my_partial.func.my_marker

meta_data, , __call__().

+2

, functools.update_wrapper.

from functools import partial, update_wrapper, WRAPPER_ASSIGNMENTS


SPECIAL_CONSTANT = 'bam'


def my_func(msg):
    print msg


my_func.my_marker = SPECIAL_CONSTANT

my_partial = partial(my_func, 'hello world')
update_wrapper(my_partial, my_func, WRAPPER_ASSIGNMENTS + ('my_marker', ))

print my_partial.my_marker
0

, cbo :

from functools import partial as _partial, update_wrapper

def partial(func, *args, **keywords):
    return update_wrapper(_partial(func, *args, **keywords), func)

, , , :

def my_func(msg):
    print msg


my_func.my_marker = 'FOO'

my_partial = partial(my_func, 'hello world')

print my_func.my_marker
print my_partial.my_marker

# check other stuff is still there
print my_partial.func
print my_partial.args
print my_partial.keywords

# this works fine for READ ONLY stuff.

# so just remember:

my_partial.my_marker = 'BAR' # this _only_ updates partial, not the original

print my_func.my_marker
print my_partial.my_marker


my_func.my_marker = 'BAZ' # this _only_ updates original, not the partial

print my_func.my_marker
print my_partial.my_marker

- :

import functools
setattr(functools, 'partial', partial) # from above code

, , , (1) , , (2) , (3) (4) , , . , .

0
source

All Articles