user1050619
user1050619

Reputation: 20916

python expression with or statement

I see the below statement in the github link and would like to how this condition is executed. The right expression to the or checks for a condition but the left side is more of a assigment statement.

https://github.com/wkentaro/labelme/blob/30a29a4a9c1f355cdbd69e65a0f3aad6948f458d/labelme/canvas.py#L464

shape.fill = shape.selected or shape == self.hShape

Upvotes: 2

Views: 81

Answers (4)

abarnert
abarnert

Reputation: 366133

You're getting the precedence wrong.1

This is an assignment statement, where the left side is the name shape.fill, and the right side is the or expression. It's not an or statement, where the left side is an assignment and the right side is a comparison.

In other words, it's equivalent to:

shape.fill = (shape.selected or shape == self.hShape)

And to avoid any other confusion, the == is evaluated before the or, so it's ultimately equivalent to this:

shape.fill = (shape.selected or (shape == self.hShape))

And hopefully you understand what that means.


The implicit precedence rules2 for every operator, symbol, and keyword can be inferred by worked out by reading the syntax in the Reference Manual, starting from Top-level components and working down through statements (simple and complex) and expressions. Or you can read the Full Grammar specification for a more concise but less explanatory version.

But since you're using Python, you might prefer to learn by experimentation rather than by manual. In that case, check out the ast module:

>>> import ast
>>> statement = 'shape.fill = (shape.selected or shape == self.hShape)'
>>> print(ast.dump(ast.parse(statement)), annotate_fields=False)
("Module([Assign([Attribute(Name('shape', Load()), 'fill', Store())], "
 "BoolOp(Or(), [Attribute(Name('shape', Load()), 'selected', Load()), "
 "Compare(Name('shape', Load()), [Eq()], [Attribute(Name('self', Load()), "
 "'hShape', Load())])]))])")

OK, that may be a bit hard to follow, but there are some nice third-party libs that format the tree more clearly. It comes down to this:

Module
    Assign
        Attribute
            Name('shape')
            'fill'
        BoolOp
            Or
            Attribute
                Name('shape')
                'selected'
            Compare
                Name('shape')
                Eq
                Attribute
                    Name('self')
                    'hShape'

So, you can see that there's an assignment (Assign) where the left side is the attribution (Attribute) and the right side is the or expression (BoolOp).


1. Technically, there's no precedence going on, because = isn't even an operator in Python. But it's easier to think about it this way, and only a tiny bit misleading, and hopefully the next sentence clears it up.

2. Again, the only explicit precedence rules are those that apply to operators, which doesn't include the = in your example. So you have to work out how the statement will be parsed, effectively the same way the parser does.

Upvotes: 3

Blckknght
Blckknght

Reputation: 104852

The or operator binds less tightly than the = you see on the left. Adding some parentheses may make the situation clearer:

 shape.fill = ((shape.selected) or (shape == self.hShape))

The parentheses I've added don't change anything in how the statement is evaluated. The two arguments to or are shape.selected (which is presumably a bool), and the expression shape == self.hShape. The result of the or expression is what gets assigned to shape.fill.

Upvotes: 2

wim
wim

Reputation: 363566

In this context, shape.selected is a boolean attribute, so the code is equivalent to this:

if shape.selected:
    shape.fill = shape.selected
else:
    shape.fill = shape == self.hShape  

Does that help?

Upvotes: 3

ritlew
ritlew

Reputation: 1682

It is evaluating the same sort of statement you would see in an if statement.

They are creating a boolean and assigning it to shape.fill. Presumably, shape.selected is either True or False. They are then applying a logical or with another boolean statement shape == self.hShape.

In the end, it is of the form

shape.fill = (boolean variable) or (boolean expression)

while evaluates to a boolean.

Upvotes: 1

Related Questions