简体   繁体   中英

Python distinguish between returned tuple and multiple values

I want to write a wrapper function which call one function and pass the results to another function. The arguments and return types of the functions are the same, but I have problem with returning lists and multiple values.

def foo():
    return 1,2

def bar():
    return (1,2)

def foo2(a,b):
    print(a,b)

def bar2(p):
    a,b=p
    print(a,b)

def wrapper(func,func2):
    a=func()
    func2(a)

wrapper(bar,bar2)
wrapper(foo,foo2)

I am searching for a syntax which works with both function pairs to use it in my wrapper code.

EDIT: The definitions of at least foo2 and bar2 should stay this way. Assume that they are from an external library.

There is no distinction. return 1,2 returns a tuple. Parentheses do not define a tuple; the comma does. foo and bar are identical.

As I overlooked until JacobIRR's comment, your problem is that you need to pass an actual tuple, not the unpacked values from a tuple, to bar2 :

a = foo()
foo2(*a)

a = bar()
bar2(a)

I don't necessarily agree with the design, but following your requirements in the comments (the function definitions can't change), you can write a wrapper that tries to execute each version (packed vs. unpacked) since it sounds like you might not know what the function expects. The wrapper written below, argfixer , does exactly that.


def argfixer(func):
    def wrapper(arg):
        try:
            return func(arg)
        except TypeError:
            return func(*arg)
    return wrapper


def foo():
    return 1,2

def bar():
    return (1,2)

@argfixer
def foo2(a,b):
    print(a,b)

@argfixer
def bar2(p):
    a,b=p
    print(a,b)


a = foo()
b = bar()

foo2(a)
foo2(b)

bar2(a)
bar2(b)

However, if you aren't able to put the @argfixer on the line before the function definitions, you could alternatively wrap them like this in your own script before calling them:

foo2 = argfixer(foo2)
bar2 = argfixer(bar2)

And as mentioned in previous comments/answers, return 1,2 and return (1,2) are equivalent and both return a single tuple.

This code does not run because of arg differences. It runs if you use def foo2(*args): and def bar2(*p): .

The return 1, 2 and return (1, 2) are equivalent. The comma operator just creates a tuple, whether it is enclosed in parentheses or not.

All programming languages that I know of return a single value , so, since you want to return multiple, those values must be wrapped into a collection type, in this case, a tuple.

The problem is in the way you call the second function. Make it bar2(a) instead of bar2(*a) , which breaks the tuple into separate arguments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM