Context-aware return

Ned Batchelder ned at
Sun Sep 13 01:27:32 CEST 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"
            ret = "Normal call"
        print ret
        return ret

    def try_it():
        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
    >>> 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...


More information about the Python-list mailing list