[Python-ideas] make __closure__ writable

Andrew Svetlov andrew.svetlov at gmail.com
Sat Mar 17 02:44:01 CET 2012


I'm ok with mutable __closure__ but can you point the real use case?

On Fri, Mar 16, 2012 at 1:58 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> Yes, your approach will work if your decorator is the only one applied.
> But, as I said, if you have many of them (see below), you can't just
> return a new function out of your decorator, you need to change the
> underlying "in-place".  Consider the following:
>
> def modifier(func):
>  orig_func = func
>
>  while func.__wrapped__:
>    func = func.__wrapped__
>
>  # patch func.__code__ and func.__closure__
>  return orig_func # no need to wrap anything
>
> def some_decorator(func):
>  def wrapper(*args, **kwargs):
>      # some code
>      return func(*args, **kwargs)
>  functools.wraps(wrapper, func)
>  return wrapper
>
> @modifier
> @some_decorator
> def foo():
>  # this code needs to be verified/augmented/etc
>
> So, in the above snippet, if you don't want to discard the
> @some_decorator by returning a new function object, you need to modify
> the 'foo' from the @modifier.
>
> In a complex framework, where you can't guarantee that your magic
> decorator will always be called first, rewriting the __closure__
> attribute is the only way.
>
> Again, since the __code__ attribute is modifiable, and __closure__
> works in tight conjunction with it, I see no point in protecting it.
>
> -
> Yury
>
> On 2012-03-16, at 3:24 PM, Mark Shannon wrote:
>
>> Yury Selivanov wrote:
>>> On 2012-03-16, at 2:57 PM, Yury Selivanov wrote:
>>>> Decorators can be nested, and what you can do in this case is to
>>>> find the most inner-wrapped function by traversing the '__wrapped__'
>>>> attributes (and check that the function you found is the actual
>>>> original function).  After that you can play with its attributes,
>>>> but you can't simply substitute the function object, as the inner
>>>> decorator won't use it.  So sometimes you have to work with the
>>>> function object without a way of substituting it.
>>> And that applies to the situations where decorators are not enough
>>> and you have to work on the opcode level.
>>
>> Which you can do with a decorator.
>>
>> Would this do what you want?
>>
>> def f_with_new_closure(f, closure):
>>    return types.FunctionType(f.__code__,
>>                              f.__globals__,
>>                              f.__name__,
>>                              f.__defaults__,
>>                              closure)
>>
>>
>> Cheers,
>> Mark.
>>
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> http://mail.python.org/mailman/listinfo/python-ideas
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas



-- 
Thanks,
Andrew Svetlov



More information about the Python-ideas mailing list