Nested arguments not compiling

PEP 3113 explains why this feature, “tuple parameter unpacking”, was removed in Python 3. It also explains how to port code that uses them. In this case you’d need to change a function like:

def add(self, (sub, pred, obj)):
    self._addToIndex(self._spo, sub, pred, obj)
    self._addToIndex(self._pos, pred, obj, sub)
    self._addToIndex(self._osp, obj, sub, pred)

to a version which passes the tuple as a single parameter and unpacks it manually:

def add(self, sub_pred_obj):
    sub, pred, obj = sub_pred_obj
    self._addToIndex(self._spo, sub, pred, obj)
    self._addToIndex(self._pos, pred, obj, sub)
    self._addToIndex(self._osp, obj, sub, pred)

For a lambda function, you can’t use assignment to unpack. The best solution there is usually to not unpack. For example, change this:

lambda (x, y): (y, x)

… to this:

lambda xy: (xy[1], xy[0])

For complicated functions, this can get ugly—but then for complicated functions, you probably want to def them anyway.


It’s worth noting that running your code through 2to3, modernize, or futurize will find this problem in both def and lambda, and suggest exactly these solutions:

$ echo 'lambda (x,y): (y,x)' | 2to3 -
--- <stdin> (original)
+++ <stdin> (refactored)
@@ -1 +1 @@
-lambda (x,y): (y,x)
+lambda x_y: (x_y[1],x_y[0])

$ echo -e 'def foo((x,y)):\n    return (y,x)\n' | 2to3 -
--- <stdin> (original)
+++ <stdin> (refactored)
@@ -1 +1 @@
-def foo((x,y)):
+def foo(xxx_todo_changeme):
+    (x,y) = xxx_todo_changeme

If you’re trying to port Python 2.x code to 3.x (or to dual-version code) and don’t know both languages, you almost certainly want to use one of these tools—or an IDE plugin that wraps them—to help. (Although you may not want to use its output as-is.)

Leave a Comment