Reputation: 51
This is basically a code golf problem I was solving. The statement goes like so:
Given N, X and a line with X numbers between 0 and 9. Print all valid numbers between 0 and N inclusive. A number is valid if all of your digits are in line. If the sequence is empty, print NONE.
And this was my first attempt:
n,x=map(int,input().split())
d=set(input().split())
print(*[v for v in range(n+1)if not set(str(v)).difference(d)]or'NONE')
Why does python unpack the string 'NONE' here? Isn't this supposed to be a simple short circuit where python prints the unpacked list if it is not empty or otherwise print the full string intact?
Upvotes: 0
Views: 284
Reputation: 44848
Apparently, Starred
has higher precedence:
>>> import ast
>>> print(ast.dump(ast.parse("print(*[] or 'NONE')"), indent=2))
Module(
body=[
Expr(
value=Call(
func=Name(id='print', ctx=Load()),
args=[
Starred(
value=BoolOp(
op=Or(),
values=[
List(elts=[], ctx=Load()),
Constant(value='NONE')]),
ctx=Load())],
keywords=[]))],
type_ignores=[])
As you can see, Starred
is applied to BoolOp
, which is the or
operator with two operands: the list and the string 'NONE'
. So you could put parentheses like this:
print(*( [] or 'NONE'))
In words, unpacking will be applied to the result of [<your list here>] or 'NONE'
.
Note: I've replaced your list comprehension with an empty list []
for the sake of brevity.
Upvotes: 1
Reputation: 34282
If you try a simpler example, e.g.:
print(*[] or 'Test')
you'll see:
T e s t
It's because the call is actually parsed as:
print(*([] or 'Test'))
Due to precedence rules. Otherwise, the expression print((*[]) or 'Test')
wouldn't even make any sense. Instead, try:
print(*[] or ['Test'])
and that will work like you expected.
Upvotes: 1