From: Steven D'Aprano on
On Wed, 10 Feb 2010 10:08:47 -0500, John Posner wrote:

>> This won't work correctly, because old_f still tries to refer to itself
>> under the name "f", and things break very quickly.
>
> They didn't break immediately for me -- what am I missing?:

The original function f doesn't try to refer to itself in any way. With
no recursive call or access, it doesn't matter what f is named.

See this example instead:


>>> def f(x):
.... if x < 0:
.... print "original"
.... return f(-x)
.... else:
.... return x+1
....
>>> f(2)
3
>>> f(-2)
original
3
>>>
>>> old_f = f
>>> def f(x):
.... if x > 0:
.... return old_f(-x)
.... else:
.... return x
....
>>> f(-1)
-1
>>> f(1)
original
original
original
original
original
original
[...]
File "<stdin>", line 3, in f
File "<stdin>", line 4, in f
File "<stdin>", line 3, in f
RuntimeError: maximum recursion depth exceeded





--
Steven
From: MRAB on
Stephen Hansen wrote:
> On Wed, Feb 10, 2010 at 6:36 AM, Steven D'Aprano
> <steve(a)remove-this-cybersource.com.au
> <mailto:steve(a)remove-this-cybersource.com.au>> wrote:
>
> On Wed, 10 Feb 2010 05:59:41 -0800, Muhammad Alkarouri wrote:
> > 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
>
> Not built-in.
>
> > 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.
>
> I completely agree with you. It is a wart that functions are only
> able to
> refer to themselves by name, because if the name changes, things break.
>
>
> I agree its slightly... in-elegant, or sub-optimal, but I'm not sure I
> want to call it a *wart*. If one calls it a wart, there might be
> inspiration to fix it.
>
> And this sounds like a precursor to making "self" non-explicit, and I
> *really* like my explicit self. :)
>
> Then again, I have been slightly bruised by this sub-optimal situation
> before.
>
> I tried to do a function using a frame hack to get the information
> easily, but failed. My long years of avoiding frame hacks like the
> plague have left me deficient. :(
>
Does this mean that Python needs, say, __function__ (and perhaps also
__module__)?
From: John Posner on
On 2/10/2010 10:24 AM, Bruno Desthuilliers wrote:
>>
>> They didn't break immediately for me -- what am I missing?:
>
> The fact that in the OP's snippet, code inside f's body refers to f by
> its name.

Of course! Tx. -John



From: Arnaud Delobelle on
Steven D'Aprano <steve(a)REMOVE-THIS-cybersource.com.au> writes:

> On Wed, 10 Feb 2010 10:08:47 -0500, John Posner wrote:
>
>>> This won't work correctly, because old_f still tries to refer to itself
>>> under the name "f", and things break very quickly.
>>
>> They didn't break immediately for me -- what am I missing?:
>
> The original function f doesn't try to refer to itself in any way. With
> no recursive call or access, it doesn't matter what f is named.
>
> See this example instead:
>
>
>>>> def f(x):
> ... if x < 0:
> ... print "original"
> ... return f(-x)
> ... else:
> ... return x+1
> ...
>>>> f(2)
> 3
>>>> f(-2)
> original
> 3
>>>>
>>>> old_f = f
>>>> def f(x):
> ... if x > 0:
> ... return old_f(-x)
> ... else:
> ... return x
> ...
>>>> f(-1)
> -1
>>>> f(1)
> original
> original
> original
> original
> original
> original
> [...]
> File "<stdin>", line 3, in f
> File "<stdin>", line 4, in f
> File "<stdin>", line 3, in f
> RuntimeError: maximum recursion depth exceeded

It's not ideal, but you can use a decorator like this to solve this
problem:

def bindfunction(f):
def bound_f(*args, **kwargs):
return f(bound_f, *args, **kwargs)
bound_f.__name__ = f.__name__
return bound_f

>>> @bindfunction
.... def factorial(this_function, n):
.... if n > 0:
.... return n * this_function(n - 1)
.... else:
.... return 1
....
>>> factorial(15)
1307674368000L
>>> fac = factorial
>>> fac(15)
1307674368000L
>>> factorial = 'foobar'
>>> fac(15)
1307674368000L

--
Arnaud
From: Steven D'Aprano on
On Wed, 10 Feb 2010 17:23:36 +0000, MRAB wrote:

> Stephen Hansen wrote:
>> On Wed, Feb 10, 2010 at 6:36 AM, Steven D'Aprano
>> <steve(a)remove-this-cybersource.com.au
>> <mailto:steve(a)remove-this-cybersource.com.au>> wrote:
>>
>> On Wed, 10 Feb 2010 05:59:41 -0800, Muhammad Alkarouri wrote:
>> > 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
>>
>> Not built-in.

[...]

> Does this mean that Python needs, say, __function__ (and perhaps also
> __module__)?

Python already has __module__, except that it is spelled:

import __main__


As for __function__, perhaps, but a solution I would be satisfied with
would be to make it optional. Most functions are not recursive, and do
not attach attributes to themselves. For the few that do need to refer to
themselves, it would be sufficient to call a decorator to get the
behaviour needed. I thought I had come up with such a thing, once before,
but I can't find it now :(


--
Steven