3

I don't understand how this syntax work and can't find documentation on it:

word = '123xyz567'
s = ''.join (c if c.isdigit() else ' 'for c in word)

Line 2 of code will take xyz123 and join together "123 567" into one string by passing in a lambda function to join

However, I am confused as to how this syntax works, normally a python if-else statement goes:

def example():
    for c in word:
        if c.isdigit():
            return c
        else:
            return ' ' 

Can someone either explain or direct me to documentation that explains to me the syntax structure of the lambda function passed into .join() and how I can use it properly?

Red
  • 26,798
  • 7
  • 36
  • 58
  • 1
    Nothing there is a lambda function. – jonrsharpe May 02 '21 at 22:38
  • https://docs.python.org/3/reference/expressions.html#conditional-expressions – iz_ May 02 '21 at 22:39
  • Please go through the [intro tour](https://stackoverflow.com/tour), the [help center](https://stackoverflow.com/help) and [how to ask a good question](https://stackoverflow.com/help/how-to-ask) to see how this site works and to help you improve your current and future questions, which can help you get better answers. "Teach me this language feature" is off-topic for Stack Overflow. Stack Overflow is not intended to replace existing tutorials and documentation. – Prune May 02 '21 at 22:59

3 Answers3

5

That's not a lambda but a generator expression.

https://www.python.org/dev/peps/pep-0289/

Almost like a list comprehension but instead a generator literal.

list = [a for a in [1,2,3]]
generator = (a for a in [1,2,3])
print(list) # [1,2,3]
print(generator) # <generator object <genexpr> at 0x7f8ee3abd6d0>
Işık Kaplan
  • 2,815
  • 2
  • 13
  • 28
2

The syntax you displayed is not a lambda function, but rather a generator expression. See: Generator expressions vs. list comprehensions

You can read more on lambda here: Why are Python lambdas useful?

The def function you displayed wouldn't work properly with the return statement; use yield so that the function won't jump out at the first character:

def example(word):
    for c in word:
        if c.isdigit():
            yield c
        else:
            yield ' ' 

More on yield here: What does the "yield" keyword do?

Red
  • 26,798
  • 7
  • 36
  • 58
2

There are several things goining on here, none of them are lambda.

The first thing is a generetor expresion, which is of the form: (<expresion> for <var> in <iterable>).
In your example <expresion> is c if c.isdigit() else ' ', <var> is c, and iterable is word.
It creates a generator (which is a sort of iterable) to pass to str.join.

The second thing is a ternary operator, which is of the form: <expresion> if <bool-expresion> else <expresion>.
In your example the first <expresion> is c, <bool-expresion> is c.isdigit(), and the second <expresion> is ' '.
It returns the first <expresion> if the <bool-expresion> evaluates to True, else it returns the second <expresion>.

Everything put together, (c if c.isdigit() else ' 'for c in word) is a generator with all the characters of word but with non-digit characters replaced with a single space (each).

Roy Cohen
  • 1,540
  • 1
  • 5
  • 22