0

I am currently using python 3.5 and Ubuntu 16.04. I have a code in python 2 and i want to use it for python 3.5. The code consists of lambda and the argument passed to it (lets say apple) consists of 3 tuples. 1st tuple is an array which looks like something this:

array([[0,0,0,0],[0,0,0,0]],dtype=uint8)  

2nd tuple consists of a pair of number like this:

(34,678)  

3rd tuple is a string and it consists of a path which points to a particular file:

'/home/king/abcd.png'  

Therefore my argument apple looks like this:

apple=(array([[0,0,0,0],[0,0,0,0]],dtype=uint8),(34,678),'/home/king/abcd.png')

Now i know the syntax has changed in python3 for lambda along with removal of tuple parameter unpacking:

lambda(x, y) : x*x , y*y (python2)  
lambda x_y : x_y[0] * x_y[0] , x_y[1] * x_y[1] (python3)  

Now my main question/problem is I want to access the first row of the 1st tuple inside lambda i.e access:

[[0,0,0,0],[0,0,0,0]]  

The parameter passed to lambda is our argument apple. My current syntax is:

lambda(x,y,z) : x[0] , y , z  (pyhton2)  

lambda x_y_z : ? , ? , ?  (python3)

Note: I am not using/trying/thinking of using python 3.8

1
  • Just don't use a lambda. It is never necessary. Commented Jan 2, 2020 at 5:25

1 Answer 1

1

The direct approach is to index into the tuple:

lambda x_y_z: (x_y_z[0][0], x_y_z[1], x_y_z[2])

You can mechanically apply this approach in any case that unpacks an indexable sequence argument, like a tuple or list. I think this one is kind of ugly, but it's fine as a first step to get your tests passing on Python 3 before a more thorough refactor.

If you're upgrading by hand anyway, you could instead nest lambdas to emulate parameter unpacking:

lambda x_y_z: (lambda x, y, z: x[0], y, z)(*x_y_z)

It's debatable whether this is more or less readable than the direct approach. I find the names easier to read than the numbers, but it's at the cost of a more complex expression. You probably shouldn't always upgrade lambdas this way because nested parameter tuples would take too many lambdas to unpack. But this approach would also be able to unpack iterators, which can't be directly indexed.

Note that you can still unpack as before by using a def in advance and an assignment statement, which may be the most readable:

def spam(x_y_z):
    x, y, z = x_y_z
    return x[0], y, z

This approach will also work on iterator arguments and for nested tuples. But you will have to come up with an appropriate function name each time.


can you explain me the meaning of *x_y_z ?

In that context (inside a call), the * passes the contents of an iterable object as positional arguments, instead of the iterable itself. Maybe an example would help:

>>> def show_args(*args):
...     print(args)
...
>>> show_args([1,2,3], 'abc')
([1, 2, 3], 'abc')
>>> show_args(*[1,2,3], *'abc')
(1, 2, 3, 'a', 'b', 'c')
Sign up to request clarification or add additional context in comments.

2 Comments

Ok. I was somewhat correct. Let me try the exact thing now(direct approach). I find it easy. Thanks !
can you explain me the meaning of ` *x_y_z ` ? @gilch

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.