Context-aware return
Ned Batchelder
ned at nedbatchelder.com
Sat Sep 12 19:27:32 EDT 2015
On Thursday, September 10, 2015 at 8:44:01 PM UTC-4, Denis McMahon wrote:
> On Fri, 11 Sep 2015 03:54:14 +1000, Steven D'Aprano wrote:
>
> > If I did this thing, would people follow me down the street booing and
> > jeering and throwing things at me?
>
> Yes
>
> >>> x = func()
> >>> x
> >>> func()
> >>> print x == func()
> >>> assert x == func()
>
> Would you expect the last two calls to func() to return 999 or "Awesome"?
> Why? What is the material difference if any between interpreter (a)
> displaying the return value and (b) comparing the return value with
> another value.
>
> Debugging nightmare!
I'll add my voice to the rising chorus condemning the very notion
of a function that behaves this way!
Then, I'll give you an implementation (Python 2):
import inspect
import opcode
def magic_return():
frame = inspect.stack()[1][0]
code = frame.f_code
next_opcode = opcode.opname[ord(code.co_code[frame.f_lasti+3])]
if next_opcode == "PRINT_EXPR":
ret = "Used at the prompt"
elif next_opcode == "POP_TOP":
ret = "Value ignored"
else:
ret = "Normal call"
print ret
return ret
def try_it():
magic_return()
x = magic_return()
print magic_return()
magic_return() + ""
This examines the byte code of the caller to determine the next
byte code after the CALL_FUNCTION that called us. The byte code
used next shows what will happen to the return value.
Try it out:
$ python -i detect_caller.py
>>> magic_return()
Used at the prompt
'Used at the prompt'
>>> try_it()
Value ignored
Normal call
Normal call
Normal call
Normal call
>>>
I'm sure there are plenty of cases this gets wrong. If you try
to pin this on me, I will swear up and down that someone hacked
into my account to send this message...
--Ned.
More information about the Python-list
mailing list