2

I've seen different questions about casting while unpacking strucutures of the same type. I.e.

def foo():
    return ('1', '2')

x, y = foo()  # as str
x, y = map(int, foo())  # as int
x, y = [int(n) for n in foo()]  # equivalently as int

But say you had

def foo():
    return ('s', '1')

and you wanted to unpack and cast only the second element of the tuple. Of course there is

x, y = foo()
y = int(y)

which, in the name of simplicity, could definitely be the most pythonic approach. Out of curiosity though, is there an even more succinct way to accomplish the same thing on a single line?

fedora
  • 201
  • 1
  • 5
  • `[f(v) for f,v in zip([str, int], foo())]` would do it in a single line. It's also an example of *why* doing things in a single line isn't necessarily a good idea... – jasonharper Jul 08 '20 at 21:13
  • Absolutely - good example. Some of these convoluted approaches crossed my mind. Asking the question only because I couldn't help wonder if there was some slick, pythonic syntax I just haven't encountered yet to do the same. – fedora Jul 08 '20 at 21:18

2 Answers2

2

You could check if the value is able to be cast to int:

x, y = [int(n) if n.isdigit() for n in foo()]

Although this won't work for negitive numbers so you could use a try/except clause

def convert(s, t=int):
    try:
        return t(s)
    except ValueError:
        return s

x, y = map(convert, foo())

Otherwise if you know every first value will be a str and the second will be int then you can use

x, y = foo(); y = int(y)

If you insist on a 1 liner

Jab
  • 26,853
  • 21
  • 75
  • 114
2

If you use Python 3.8+, you can use assignment expression :=

def foo():
    return ('s', '1')

x, y = (v:=foo())[0], int(v[1])
print(x, y)

Prints:

s 1
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91