determining the number of output arguments

Peter Otten __peter__ at web.de
Tue Nov 16 03:47:46 EST 2004


Darren Dale wrote:

> I want to extend the capabilities of an existing function without breaking
> backward compatibility. I used nargin and nargout (number of arguments in
> and out) pretty extensively in Matlab.

Here is another alternative to achieve backward compatibility:

class Result(object):
    def __init__(self, a, b, c, d):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
    def __iter__(self):
        yield self.a
        yield self.b
        yield self.c
                    
def old():
    return 1, 2, 3
    
def new():
    return Result(1, 2, 3, 4)

# the old function    
a, b, c = old()
print a, b, c

# the new function, called by old code
a, b, c = new()
print a, b, c

# the new function, called by new code
r = new()
print r.a, r.b, r.c, r.d

If old code doesn't always immediately unpack, you can implement
__getitem__(), too, or subclass tuple:

class Result(tuple):
    def __new__(cls, *items):
        items = list(items)
        if len(items) == 3:
            d = None
        elif len(items) == 4:
            d = items[-1]
            items = items[:-1]
        else:
            raise ValueError
        result = tuple.__new__(cls, items)
        result.d = d
        return result

    a = property(lambda self: self[0])
    b = property(lambda self: self[1])
    c = property(lambda self: self[2])

In effect you are switching to an object-oriented interface while staying
compatible with old code. This makes future updates a breeze, e. g. if the
calculation of d is costly you could defer it until really needed:

    class Result(object):
        ...
        d = property(lambda self: max(self.a, self.b, self.c) + 42)

Peter




More information about the Python-list mailing list