Syntax error on a piece of code which is accepted as an argument to str.join

Viewed 26

Please clarify this behavior in python3:

>>> ''.join('<%s>%s</%s>' % (tag, content, tag) for tag, content in {'b': 'bold'}.items())
'<b>bold</b>'

>>> '<%s>%s</%s>' % (tag, content, tag) for tag, content in {'b': 'bold'}.items()
File "<stdin>", line 1
'<%s>%s</%s>' % (tag, content, tag) for tag, content in {'b': 'bold'}.items()
                                      ^
SyntaxError: invalid syntax

From https://docs.python.org/3/library/stdtypes.html#str.join, its argument is supposed to be an iterable. If you look closely, the same argument provided to join in this example is giving an syntax error when inspected by itself.

I don't understand how this is supposed to work as an argument but can't be inspected as a value.

Thanks for your attention.

1 Answers

This is because you are passing a generator expression as an argument to the join method (see this bit of documentation and this bit).

When this kind of expression is used as an argument to a call, you can omit the parentheses.

If you surround the expression with parentheses in a Python interpreter, you will see something like this:

>>> ('<%s>%s</%s>' % (tag, content, tag) for tag, content in {'b': 'bold'}.items())
<generator object <genexpr> at 0x7f2ab9b044f8>

Note that you can confirm that you don't need the parentheses when it is part of an argument to a call like so:

>>> type('<%s>%s</%s>' % (tag, content, tag) for tag, content in {'b': 'bold'}.items())
<class 'generator'>

From the official documentation:

Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict, file objects [...] Iterables can be used in a for loop and in many other places where a sequence is needed [...] See also iterator, sequence, and generator.

Related