Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
308 views
in Technique[技术] by (71.8m points)

python - Find out into how many values a return value will be unpacked

I have a function, and when it is called, I'd like to know what the return value is going to be assigned to - specifically when it is unpacked as a tuple. So:

a = func()         # n = 1

vs.

a, b, c = func()   # n = 3

I want to use the value of n in func. There must be some magic with inspect or _getframe that lets me do this. Any ideas?


Disclaimer (because this seems to be neccessary nowadays): I know this is funky, and bad practice, and shouldn't be used in production code. It actually looks like something I'd expect in Perl. I'm not looking for a different way to solve my supposed "actual" problem, but I'm curious how to achive what I asked for above. One cool usage of this trick would be:

ONE, TWO, THREE = count()
ONE, TWO, THREE, FOUR = count()

with

def count():
    n = get_return_count()
    if not n:
        return
    return range(n)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Adapted from http://code.activestate.com/recipes/284742-finding-out-the-number-of-values-the-caller-is-exp/:

import inspect
import dis

def expecting(offset=0):
    """Return how many values the caller is expecting"""
    f = inspect.currentframe().f_back.f_back
    i = f.f_lasti + offset
    bytecode = f.f_code.co_code
    instruction = ord(bytecode[i])
    if instruction == dis.opmap['UNPACK_SEQUENCE']:
        return ord(bytecode[i + 1])
    elif instruction == dis.opmap['POP_TOP']:
        return 0
    else:
        return 1

def count():
    # offset = 3 bytecodes from the call op to the unpack op
    return range(expecting(offset=3))

Or as an object that can detect when it is unpacked:

class count(object):
    def __iter__(self):
        # offset = 0 because we are at the unpack op
        return iter(range(expecting(offset=0)))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...