renaming 'references' to functions can give recursive problems

P

peter

Hello all,

Recently I've started to refactor my code ...(I'm using python 2.3.4)
I tried to add extra functionality to old functions non-intrusively.
When I used a construct, which involves renaming functions etc... I
came across some recursive problems. (a basic construct can be found
under the section BASIC CODE)

These problems do not occur when renaming objects. (see section EXTRA
CODE)
My question now is:
I do not know the underlying idea of functions. Is this the way they
should behave? Or should they work the same way as objects do?
(My preferences goes to this last option)

BASIC CODE:
---------------------------------------------------------------------------
def fA(input): # starting point: function named fA
return input

def newFA(input): # new function with added functionality
#does something extra with a!
return fA(input)
fA = newFA
# this should allow to add functionality without
# breaking older code which uses the name fA!
fA() # execute fA()
----------------------------------------------------------------------------
problem: you get...
File "recursivemethods.py", line 7, in newFA
return fA(input)
RuntimeError: maximum recursion depth exceeded

when using objects this problems does not occur...
EXTRA CODE:
----------------------------------------------------------------------------
PYTHON-CODE # REMARKS
referenceA = SomeObject() # referenceA -> SomeObject()
# references to the memory space of
# some object
referenceB = referenceA # referenceB -> SomeObject()
# is also a reference to ...
referenceA = referenceB # referenceA references to SomeObject()

# now for functions!
fA = function # fA references to memory space
# of a function

def newFA(input): # newFA references to a function
return fA(input) # which holds a reference to fA.
# Notice the important difference with objects!
# newFA holds a reference to the reference fA
# When using object you reference to
# the memory space of fA!!!
fA = newFA
fA() # recursive problems!!!
--------------------------------------------------------------------------
 
P

peter

see the topic:
adding new functionality to a function non-intrusively! and decorators
if you want to add functionality to a function!
 
A

Antoon Pardon

Op 2005-02-16 said:
Hello all,

Recently I've started to refactor my code ...(I'm using python 2.3.4)
I tried to add extra functionality to old functions non-intrusively.
When I used a construct, which involves renaming functions etc... I
came across some recursive problems. (a basic construct can be found
under the section BASIC CODE)

These problems do not occur when renaming objects. (see section EXTRA
CODE)
My question now is:
I do not know the underlying idea of functions. Is this the way they
should behave? Or should they work the same way as objects do?
(My preferences goes to this last option)

BASIC CODE:
---------------------------------------------------------------------------
def fA(input): # starting point: function named fA
return input

def newFA(input): # new function with added functionality
#does something extra with a!
return fA(input)
fA = newFA
# this should allow to add functionality without
# breaking older code which uses the name fA!
fA() # execute fA()

Try this:

def fA(input):
return input


def newFA(input, f= fA):
return f(input)

fA = newFA
 
P

peter

Hello, nice solution:
but it puzzles me :)

can anyone tell me why
-----------correct solution----------------
def fA(input):
return input

def newFA(input, f= fA):
return f(input)

fA = newFA

is correct and:
-------------infinite loop-----------------

def fA(input):
return input

def newFA(input):
return fA(input)

fA = newFA

gives an infinite recursive loop?

kind regards

Peter
 
S

Satchidanand Haridas

peter said:
Hello, nice solution:
but it puzzles me :)

can anyone tell me why
-----------correct solution----------------
def fA(input):
return input

def newFA(input, f= fA):
return f(input)

fA = newFA

is correct and:
.... print "inside fA"
.... return input
........ print "inside newFA"
.... return f(input)
....inside newFA
inside fA
2

while:
-------------infinite loop-----------------

def fA(input):
return input

def newFA(input):
return fA(input)

fA = newFA

gives an infinite recursive loop?
.... print "inside fA"
.... return input
........ print "inside newFA"
.... return fA(input)
....inside newFA
inside newFA
inside newFA
inside newFA


What is happening is that when you call fA (inside newFA) in the second
case, you are calling newFA because fA is pointing to newFA (hope that
made sense ;-)). So it was recursive. While in the former case you
called f, which pointed to fA, but not to newFA. Probably the following
will make it clearer:

.... print "inside fA"
.... return input
........ print "inside newFA"
.... print "f is pointing to: ",f
.... return f(input)
....inside newFA
f is pointing to: <function fA at 0x43123374>
inside fA
2<function newFA at 0x43194064>

Thus f and fA do not point to the same function object when you execute
the statement fa(2). This f is called once and terminates.


thanks,
Satchit
 
M

Michael Spencer

peter said:
Hello, nice solution:
but it puzzles me :)

can anyone tell me why
-----------correct solution----------------
def fA(input):
return input

def newFA(input, f= fA):
return f(input)

fA = newFA

is correct and:
-------------infinite loop-----------------

def fA(input):
return input

def newFA(input):
return fA(input)

In newFA, fA is not bound until you call newFA. By which time you've re-bound
fA to newFA, causing the recursion. In the 'correct' solution above, f is bound
to the original fA function at the time the def fA statement is executed, which
is what you want.
fA = newFA

gives an infinite recursive loop?

kind regards

Peter

Regards
Michael
 
F

Fredrik Lundh

peter said:
----------------------------------------------------------------------------
PYTHON-CODE # REMARKS
referenceA = SomeObject() # referenceA -> SomeObject()
# references to the memory space of
# some object
referenceB = referenceA # referenceB -> SomeObject()
# is also a reference to ...
referenceA = referenceB # referenceA references to SomeObject()

# now for functions!
fA = function # fA references to memory space
# of a function

nope. it refers to a function object. function objects are no different
from ordinary objects.
def newFA(input): # newFA references to a function

not yet.
return fA(input) # which holds a reference to fA.

nope. the function does not hold a reference to fA. fA is a global,
and will be resolved at runtime.
# Notice the important difference with objects!
# newFA holds a reference to the reference fA

no, it doesn't hold a reference to the reference. it contains the name
"fA", and will look for that when you call it.
# When using object you reference to
# the memory space of fA!!!

you're confused. resetting your brain and reading the documentation
again might help:

http://docs.python.org/ref/objects.html
http://docs.python.org/ref/naming.html

</F>
 
J

Jeff Shannon

peter said:
Hello, nice solution:
but it puzzles me :)

can anyone tell me why
-----------correct solution----------------
def fA(input):
return input

def newFA(input, f= fA):
return f(input)

This saves a reference to the original function in the new function's
default argument.
-------------infinite loop-----------------

def fA(input):
return input

def newFA(input):
return fA(input)

This does not save any reference to the original function; it simply
does a run-time lookup of the name, and uses whatever object is
currently bound to that name. Since you later rebind the name to this
new function, it's simply calling itself.

Jeff Shannon
Technician/Programmer
Credit International
 
M

Michael Spencer

peter said:
brain reset and understood

thx a lot for all your answers

Peter
Now that you've got reset, you might want to consider an alternative solution:

def fA(input):
return input

oldfA = fA # Hold a reference to the the old function

def newFA(input):
"Do something new"
return oldfA(input)

fA = newFA


The advantage of this is that you don't need to change the function newfA at all
when you're ready to rename it.

Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,162
Latest member
GertrudeMa
Top