From: Gabriel Genellina on
En Thu, 11 Feb 2010 00:25:00 -0300, Terry Reedy <tjreedy(a)udel.edu>
escribi�:
> On 2/10/2010 4:49 PM, Gabriel Genellina wrote:
>
>> I've written a decorator for "injecting" a __function__ name into the
>> function namespace, but I can't find it anywhere. I think I implemented
>> it by adding a fake additional argument and replacing LOAD_GLOBAL with
>> LOAD_NAME in the bytecode.
>
> The decorator only needs to replace the defaults args tuple.
> It does not even need to know the parameter name,
> just that it is the only (or last) with a default .
>
> def f(n, me=None):
> if n > 0: return n*me(n-1)
> elif n==0: return 1
>
> f.__defaults__ = (f,) # 3.1
> print(f(5))

This is simple to implement, but requires changing the function
definition. My goal was to keep the original code unchanged, that is,
leave it as:

def f(n):
if n > 0: return n*f(n-1)
elif n==0: return 1

(like a normal, recursive function), and make the 'f' inside the function
body "magically" refer to the function itself.

> Of course, user could still screw up recursion by providing another
> value for 'me'. This strikes me as about a likely (low) as a user
> screwing up recursion in a library module function by rebinding the name
> in the imported module.

Well, if people really want to shoot themselves in the foot, there's
nothing we can do to avoid that...

--
Gabriel Genellina

From: Terry Reedy on
On 2/11/2010 6:36 PM, Gabriel Genellina wrote:

> This is simple to implement, but requires changing the function
> definition. My goal was to keep the original code unchanged, that is,
> leave it as:
>
> def f(n):
> if n > 0: return n*f(n-1)
> elif n==0: return 1
>
> (like a normal, recursive function), and make the 'f' inside the function
> body "magically" refer to the function itself.

Someone did this several years ago with a bytecode hack. I believe it
was in the cookbook. It was rejected as part of standard CPython.

From: Arnaud Delobelle on
"Gabriel Genellina" <gagsl-py2(a)yahoo.com.ar> writes:

> En Thu, 11 Feb 2010 00:25:00 -0300, Terry Reedy <tjreedy(a)udel.edu>
> escribió:
>> On 2/10/2010 4:49 PM, Gabriel Genellina wrote:
>>
>>> I've written a decorator for "injecting" a __function__ name into the
>>> function namespace, but I can't find it anywhere. I think I implemented
>>> it by adding a fake additional argument and replacing LOAD_GLOBAL with
>>> LOAD_NAME in the bytecode.
>>
>> The decorator only needs to replace the defaults args tuple.
>> It does not even need to know the parameter name,
>> just that it is the only (or last) with a default .
>>
>> def f(n, me=None):
>> if n > 0: return n*me(n-1)
>> elif n==0: return 1
>>
>> f.__defaults__ = (f,) # 3.1
>> print(f(5))
>
> This is simple to implement, but requires changing the function
> definition. My goal was to keep the original code unchanged, that is,
> leave it as:
>
> def f(n):
> if n > 0: return n*f(n-1)
> elif n==0: return 1
>
> (like a normal, recursive function), and make the 'f' inside the function
> body "magically" refer to the function itself.

I posted an example of a decorator that does just this in this thread a
couple of days ago:

http://mail.python.org/pipermail/python-list/2010-February/1235742.html

It doesn't require any bytecode hacking, although it requires breaking
apart the function object and making a new one from the bits.

--
Arnaud
From: Gabriel Genellina on
En Fri, 12 Feb 2010 04:29:12 -0300, Arnaud Delobelle
<arnodel(a)googlemail.com> escribi�:

> I posted an example of a decorator that does just this in this thread a
> couple of days ago:
>
> http://mail.python.org/pipermail/python-list/2010-February/1235742.html

Ouch! I didn't see your post, nor several other earlier posts in this
thread. In fact, I thought mine was the *first* reply when I wrote it!

Yes, of course, your code does exactly that without any bytecode hacks.

--
Gabriel Genellina

From: Steve Howell on
On Feb 10, 5:59 am, Muhammad Alkarouri <malkaro...(a)gmail.com> wrote:
> Hi everyone,
>
> What is the simplest way to access the attributes of a function from
> inside it, other than using its explicit name?
> In a function like f below:
>
> def f(*args):
>     f.args = args
>     print args
>
> is there any other way?
> I am guessing the next question will be: should I really care? It just
> feels like there should be a way, but I am not able to verbalise a
> valid one at the moment, sorry.
>

You should care. :)

You can avoid referring to f twice by using an inner method with a
name that is less subject to change or influence from outside forces:

def countdown_function_that_might_get_renamed(
n,
preamble,
postamble):
def recurse(n):
print preamble, n, postamble
if n:
recurse(n-1)
recurse(n)

countdown_function_that_might_get_renamed(10, "before", "after")

Note that the example makes the recursive call more concise, by
avoiding the need to resend the parameters that don't change during
the recursion ("preamble" and "postamble"). Of course, you do trade
off some terseness with the inner method, but it's only two lines of
code and one level of indentation.

For a somewhat related discussion see this short thread:

http://groups.google.com/group/comp.lang.python/browse_thread/thread/197221f82f7c247b

In particular see Gabriel's response to me. The fact that you are
saving off f.args makes me think that you are solving a problem
similar to mine, but I could be wrong.