Most Pythonic Way To Port This Tuple Unpacking With Lambda From Python 2 Into Python 3
Solution 1:
I think the best solution would be to not use map
and lambda
, use a list comprehension instead:
accs += [a == b for a, b in zip(lab, lab_pred)]
Solution 2:
If you prefer functional style there is:
from operator import eq
from itertools import starmap
accs.extend(starmap(eq, zip(lab, lab_pred)))
Solution 3:
This is an intentional regression in Python3 (although I don't know the rationale - if you happen to - please comment below) in order to discourage lambda
and in the long run - using Python2 altogether.
Pythonic quick fix
(edited, previous idea didn't really work) See also here: https://stackoverflow.com/a/47947955/1338797
If your lambda is flat, there is an upgrade path to Python3:
lambda (x, y): x + y
becomes
lambda xy: (lambda x, y: x + y)(*xy)
Nice, but it has 2 downsides:
Welcome to Lisp ;) It's intricate (but pythonic, like
str.join
)It won't cut nested tuples like:
lambda ((x0, y0), (x1, y1)): abs(x1-x0) + abs(y1-y0)
An extra lambda.
Why are they forcing us to use small def
functions?
Lambdas are bad for a couple of reasons (about 3-4 may be valid):
Just because:
lambda
is broken in Python. It's "pythonic" to know this.Lambdas (in Python, not in some other language! I won't repeat this disclaimer in the following points) can only handle single expressions.
Lambdas have no
__name__
s.Lambdas have ugly
__repr__
esentations.Lambdas
arecan make code slow. (when often created unnecessarily)Lambdas are slow. (to run, compared to competing constructs)
(5 & 6 are relevant only in most performance-critical code anyway).
Small functions in Python are recommended, and they think it's no problem, because it only takes 2 lines more. (2 instead of 0, because a lambda can be inline). Thus lambda x, y: x == y
becomes:
def are_equal(x, y):
return x == y
(forget operator.eq
here, not every lambda will have it's equivalent in this module anyway).
Actually, if you stick to PEP-8, this function takes 4 extra lines in local scope, and 6 extra lines in global scope, including empty line padding.
Example situation: how to keep compatibility
Suppose you have a list, or other iterable of tuples. You want to get a max value using max(..., key=...)
. After that, you can directly unpack the tuple. In the days of Python2 it would be:
x, y, w, h = max(faces, key=lambda (x, y, w, h): w * h)
(Again, you could lecture me here about the superiority of typing.Namedtuple
s, dataclasses
, or @attr.s
, but right now I get a list
of tuple
s from OpenCV.
I found the least painful way to be to use a function:
def face_area(*args):
x, y, w, h = args if len(args) == 4 else args[0]
return w * h
x, y, w, h = max(faces, key=face_area)
Python2 will get a nested tuple in args
, and Python3 will get a tuple of length 4. You can unpack it manually as above, and then proceed with return
ing your result.
Some would say, it gives the code an occasion to become more self-documented, because I've had to think of a name for the key
function.
Post a Comment for "Most Pythonic Way To Port This Tuple Unpacking With Lambda From Python 2 Into Python 3"