Velocity Reviews > adding new functionality to a function non-intrusively!

# adding new functionality to a function non-intrusively!

peter
Guest
Posts: n/a

 02-16-2005
Hello all,

Recently I've started to refactor my code ...
I would like to add extra functionality to a function !non-intrusively!
(not rewriting the old code is really important)
How can I achieve this?

Thus I start with an old function named fA.
I would like to add extra functionality to fA.
Essentially this gives a new function fA which can call the old
function fA

thanks a lot for reading so far

Peter

ps.
following idea does not work!
# fA = old fA, already defined
def tempFunc(*args):
# do something with fA
return
fA = tempFunc # gives infinite loop, recursive mails
# this example is explained in more detail in other mail called:
"renaming 'references' to functions gives recursive problems'

mjs7231
Guest
Posts: n/a

 02-16-2005
Whenever I want to add functionality to a function while still allowing
it to word as it was before my edit would be to include a few optional
variables passed to the string. something to this effect would look
like:

------------------------------------------
BEFORE:
------------------------------------------
def myfunction(a, b):
return (a + b)
------------------------------------------
AFTER:
------------------------------------------
def myfunction(a, b, op="add"):
if (op == "add"):
return (a + b)
else:
return (a - b)
------------------------------------------

Michele Simionato
Guest
Posts: n/a

 02-16-2005
Decorators are your friends. You can wrap a function
and give it additional functionality. For instance just
yesterday I needed to keep track of how many times
a function is called. This can be done with this
decorator:

..def with_counter(f):
.. def wrappedf(*args, **kw):
.. wrappedf.counter += 1
.. return f(*args, **kw)
.. wrappedf.counter = 0
.. wrappedf.func_name = f.func_name
.. return wrappedf

..@with_counter # requires Python 2.4
..def g():
.. print "called"

..print g.counter
..g()
..print g.counter

This is intented just as an appetizer. Look at the
cookbook for more examples.

Michele Simionato

peter
Guest
Posts: n/a

 02-16-2005
Hello

I indeed also rely on your idea.
My problem however is: is has to be non-intrusively in both ways.

In your example, it would indeed not break the old code which relies on
myfunction
but my problems is: I also do not want to change the code of the
'before' myfunction.

so my problem in fact is:
BEFORE:
def myfunction(a,b):
return (a+b)
AFTER:
if (op == "add"):
# some function which calls the old code for myfunction

kind regards

peter
Guest
Posts: n/a

 02-16-2005
thx a lot for the information on decorators

this will be very usefull... (sounds like a little step towards aspect
orientated programming, )

Because I use libraries which rely on boost-python I can not jump into
python 2.4

but I understand the main idea and can also use it in python 2.3
(it will only cost a little bit more extra coding)

Terry Reedy
Guest
Posts: n/a

 02-16-2005

"peter" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> so my problem in fact is:
> BEFORE:
> def myfunction(a,b):
> return (a+b)
> AFTER:
> def myfunction(a,b, op="add"):
> if (op == "add"):
> # some function which calls the old code for myfunction

Is this wrapping what you want?

_myfunction = myfunction
if (op == 'add'): return _myfunction(a,b)
# else do new stuff and return

Terry J. Reedy

peter
Guest
Posts: n/a

 02-16-2005
indeed it does, so basically everything works except my original
solution:

def myfunction(a,b):
return a+b

def _myfunction(a,b):
return myfunction(a,b)
myfunction = _myfunction

oh well, it was enough to puzzle my tiny brain....

Terry Reedy
Guest
Posts: n/a

 02-17-2005

"peter" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> indeed it does, so basically everything works except my original
> solution:
>
> def myfunction(a,b):
> return a+b
>
> def _myfunction(a,b):
> return myfunction(a,b)
> myfunction = _myfunction
>
> oh well, it was enough to puzzle my tiny brain....

For newbies reading this, the point is that names within functions,
including global function names, are looked up when and each time the
function is *called*, not when it is defined. So even though _myfunction
does not *look* recursive, since it appears to call some other function,
the name rebinding after *makes* it recursive. Conversely, we can make a
recursive-looking function not recursive.
>>> def f(): return f() # sure looks infinitely recursive

....
>>> g = f
>>> f = int # arbitrary choice of function that will accept no args
>>> f()

0
>>> g()

0

Moral: be careful about rebinding function names, and the order in which
you do so.

Terry J. Reedy