By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,035 Members | 1,984 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,035 IT Pros & Developers. It's quick & easy.

Returning actual argument expression to a function call?

P: n/a
Hi,
# If I have a function definition
def f1(arg):
global capturecall
if capturecall:
...
do_normal_stuff(arg)

# and its later use:
def f2():
...
return f1(a and (b or c))

# I would like to do:
capturecall = False
result = f2()
# And get the equivalent of do_normal_stuff(a and(b or c))

# But also to do:
capturecall = True
result = f2()
# And get the same result, but also save the actual
# calling arguments to f1 either as a string:
# "a and (b or c))"
# Or a code object computing a and(b or c)
# I caould change f1 to expect a function instead and do:
def f1b(arg):
global capturecall
if capturecall:
save(arg)
return do_normal_stuff(arg())

# And then use it like this:
def f2b():
...
return f1b(lambda : (a and (b or c)) )

# The problem is that for my application to work,
# Python newbies would have to write lambda when they
# know they are after the result. Its my program
# that would require the lambda (or def), which
# is a distraction from their problem.

Any ideas on implementing f1 so I can do f2?

Thanks in advance, Paddy.
P.S. You might also have multiple calls where I
would need to capture each individual argument
expression of f1 e.g:
def f3():
...
return f1(a and b) or e or f1(c and d)

Nov 10 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
On Fri, 09 Nov 2007 22:03:00 -0800, Paddy wrote:
Hi,
# If I have a function definition
....
# The problem is that for my application to work,
# Python newbies would have to write lambda when they
# know they are after the result.
I don't understand why you think this is the case.

Its my program
# that would require the lambda (or def), which
# is a distraction from their problem.
....
Any ideas on implementing f1 so I can do f2?
I've read your post three times now, and I'm still not absolutely sure
what you're trying to accomplish.

I think you want something like this:

You have a function f1(*args) which returns a result. You want a global
flag that tells f1 to stick it's arguments in a global variable. Am I
close?

If so, something like this should work:

# Define someplace to store the arguments.
last_args = (None, None)
# And a flag.
capturecall = True

# A decorator to wrap a function.
def capture_args(func):
def f(*args, **kwargs):
if capturecall:
global last_args
last_args = (args, kwargs)
return func(*args, **kwargs)
f.__name__ = "capturing_" + func.__name__
return f

Now you can do this:
>>def f1(x, y=3):
.... return x + y
....
>>f1 = capture_args(f1)
f1(5)
8
>>last_args
((5,), {})
>>@capture_args
.... def f2(x):
.... return 2**x
....
>>f2(0.4+1)
2.6390158215457884
>>last_args
((1.3999999999999999,), {})

In the second example, if you are trying to capture the expression "0.4
+1", I don't think that is possible. As far as I know, there is no way
for the called function to find out how its arguments were created. I
think if you need that, you need to create your own parser.

--
Steven.
Nov 10 '07 #2

P: n/a
En Sat, 10 Nov 2007 03:03:00 -0300, Paddy <pa*******@googlemail.com>
escribió:
Hi,
# If I have a function definition
def f1(arg):
global capturecall
if capturecall:
...
do_normal_stuff(arg)

# and its later use:
def f2():
...
return f1(a and (b or c))

# But also to do:
capturecall = True
result = f2()
# And get the same result, but also save the actual
# calling arguments to f1 either as a string:
# "a and (b or c))"
# Or a code object computing a and(b or c)
Would be enough to have the source line text?

<code test1.py>
def extract_caller_info():
import sys, traceback
return traceback.extract_stack(sys._getframe(2), limit=1)

def f1(arg):
if capturecall:
print extract_caller_info()
# do_normal_stuff(arg)

def f2():
a,b,c = 1,0,3
return f1(a and (b or c))

capturecall = True
result = f2()
</code>

output is like this:
[('test1.py', 12, 'f2', 'return f1(a and (b or c))')]

source file name, line number, function name, source line text.
P.S. You might also have multiple calls where I
would need to capture each individual argument
expression of f1 e.g:
def f3():
...
return f1(a and b) or e or f1(c and d)
Tell your users that they'll have better results if those two calls are
split on different lines:

def f3():
return (f1(a and b)
or e
or f1(c and d))

Output:
[('test1.py', 18, 'f3', 'return (f1(a and b)')]
[('test1.py', 20, 'f3', 'or f1(c and d))')]

--
Gabriel Genellina

Nov 10 '07 #3

P: n/a
On Nov 10, 6:54 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.auwrote:
In the second example, if you are trying to capture the expression "0.4
+1", I don't think that is possible. As far as I know, there is no way
for the called function to find out how its arguments were created. I
think if you need that, you need to create your own parser.

--
Steven.
Unfortunately Steven, its exactly the expression that I want
rather than the expression result.

Thanks for your attempt, and I will try and make myself clearer
in the future (allthough I did take time over my initial post).

- Paddy.
Nov 10 '07 #4

P: n/a
On Nov 10, 7:02 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
En Sat, 10 Nov 2007 03:03:00 -0300, Paddy <paddy3...@googlemail.com>
escribió:
Hi,
# If I have a function definition
def f1(arg):
global capturecall
if capturecall:
...
do_normal_stuff(arg)
# and its later use:
def f2():
...
return f1(a and (b or c))
# But also to do:
capturecall = True
result = f2()
# And get the same result, but also save the actual
# calling arguments to f1 either as a string:
# "a and (b or c))"
# Or a code object computing a and(b or c)

Would be enough to have the source line text?

<code test1.py>
def extract_caller_info():
import sys, traceback
return traceback.extract_stack(sys._getframe(2), limit=1)

def f1(arg):
if capturecall:
print extract_caller_info()
# do_normal_stuff(arg)

def f2():
a,b,c = 1,0,3
return f1(a and (b or c))

capturecall = True
result = f2()
</code>

output is like this:
[('test1.py', 12, 'f2', 'return f1(a and (b or c))')]

source file name, line number, function name, source line text.
P.S. You might also have multiple calls where I
would need to capture each individual argument
expression of f1 e.g:
def f3():
...
return f1(a and b) or e or f1(c and d)

Tell your users that they'll have better results if those two calls are
split on different lines:

def f3():
return (f1(a and b)
or e
or f1(c and d))

Output:
[('test1.py', 18, 'f3', 'return (f1(a and b)')]
[('test1.py', 20, 'f3', 'or f1(c and d))')]

--
Gabriel Genellina

Thanks Gabriel, that will alow me to move forward.

Nov 10 '07 #5

P: n/a
>>>>Paddy <pa*******@googlemail.com(P) wrote:
>PHi,
P# If I have a function definition
Pdef f1(arg):
P global capturecall
P if capturecall:
P ...
P do_normal_stuff(arg)
>P# and its later use:
Pdef f2():
P ...
P return f1(a and (b or c))
>P# I would like to do:
Pcapturecall = False
Presult = f2()
P# And get the equivalent of do_normal_stuff(a and(b or c))
>P# But also to do:
Pcapturecall = True
Presult = f2()
P# And get the same result, but also save the actual
P# calling arguments to f1 either as a string:
P# "a and (b or c))"
P# Or a code object computing a and(b or c)
>P# I caould change f1 to expect a function instead and do:
Pdef f1b(arg):
P global capturecall
P if capturecall:
P save(arg)
P return do_normal_stuff(arg())
>P# And then use it like this:
Pdef f2b():
P ...
P return f1b(lambda : (a and (b or c)) )
>P# The problem is that for my application to work,
P# Python newbies would have to write lambda when they
P# know they are after the result. Its my program
P# that would require the lambda (or def), which
P# is a distraction from their problem.
>PAny ideas on implementing f1 so I can do f2?
With Python this can't be done without either quoting the expression (make
a string out of it) or using a lambda. Lisp and C# can do this kind of thing.
--
Piet van Oostrum <pi**@cs.uu.nl>
URL: http://www.cs.uu.nl/~piet [PGP 8DAE142BE17999C4]
Private email: pi**@vanoostrum.org
Nov 10 '07 #6

P: n/a
On Nov 10, 3:44 pm, Piet van Oostrum <p...@cs.uu.nlwrote:
With Python this can't be done without either quoting the expression (make
a string out of it) or using a lambda. Lisp and C# can do this kind of thing.
<WarpedHumour>
I'd like to propose we add '(<expr>) to Python. Pronounced tick-
brackets, it
surrounds an expression which is compiled into an anonymous function.

I have not thought this through apart from knowing that this is one
more
step towards Lisp heaven and submit no code as the implementation
will be trivial ;-)

Of course if my suggestion is not welcomed with open arms then this
is
Pythons last chance to escape terminal decline....
<WeftedHumour>
Nov 10 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.