![[Formales]]
![[operator_precedence_python__645127840.png]]
[Precedence and Associativity of Operators in Python](https://www.programiz.com/python-programming/precedence-associativity)<br> Author: *Programiz*
> [!multi-column]
>
>> [!BLANK]
>> - [[Unary Operator]]
>> - [[Lambda]]
>> - [[Copy vs Identity]]
>> - [[Basic Algebraic Operations]]
>> - [[Basic Decision Structures]]
>
>> [!BLANK]
>> - [[Decision Structure]]
>> - [[Decision Structure - Pharmacy]]
>> - [[Boolean Operations]]
>> - [[Bitwise Operations]]
>> - [[Operators]]
> [!TLDR] Set of rules
> - Operator precedence in Python refers to the set of rules that dictate the order in which operators are evaluated when an expression is executed.
> - These rules are essential to ensure that expressions are evaluated in the correct order and produce the expected results.
# Highest to lowest Precedence
For operators on the same row of the precedence table below:
- There is no precedence order among them; they are at the same level of precedence.
- Their evaluation order in an expression is determined by their associativity, not by their position on the row.
- Knowing the associativity is essential for correctly understanding how expressions involving operators of the same precedence are evaluated.
> [!multi-column]
>
>> [!NOTE] P
>> Precedence
>
>> [!NOTE] O
>> Operator
>
>> [!NOTE] A
>> Associativity
|P|OP|Description|A|
|:--:|---:|:--------|--|
|1|`()`|Parentheses. Used to group expressions and override the default precedence.||
|2|`.(dot)`|OOP: Attribute Access|LtR|
|3|`**`|Exponentiation|RtL|
|4|`+x`, `-x`, `~x`|[[Unary Operator]]: plus, minus, bitwise NOT|RtL|
|5|`*`, `/`, `//`, `%`|Multiplication, Division, [[Floor Division]], Modulo|LtR|
|6|`+`, `-`|Addition and subtraction|LtR|
|7|`<<`, `>>`|Left and right bitwise shifts|LtR|
|8|`&`|[[Bitwise Operations\|Bitwise]] AND|LtR|
|9|`^`|[[Bitwise Operations\|Bitwise]] XOR|LtR|
|10|`│`|[[Bitwise Operations\|Bitwise]] OR|LtR|
|11|`==`, `!=`, `<`, `<=`, `>`, `>=`|[[Comparisons]]|LtR, Chaining|
|12|`in`, `not in`|Membership; Containment|LtR|
|13|`is`, `is not`|Identity|LtR|
|14|`not`|[[Boolean Operations\|Logical]] Negation|RtL|
|15|`and`|[[Boolean Operations\|Logical]] Conjunction|LtR|
|16|`or`|[[Boolean Operations\|Logical]] Disjunction|LtR|
|17|`x if C else y`|[[Decision Structure\|Conditional]] Expression|RtL|
|18|`lambda x: x + 1`|[[Lambda]] Expression|RtL|
|19|`=`, `+=`, `-=`, `*=`, `/=`, `//=`, `%=`, `**=`, `&=`, `│=`, `^=`, `<<=`, `>>=`|Assignment|RtL|
# Left to right Associativity (LtR)
> [!TLDR]
> Associativity becomes important in expressions where multiple operations occur with operators of the same precedence.
Left-to-right associativity refers to the order in which operations of the same precedence are processed. When operators have left-to-right associativity, it means that operations are performed from left to right when multiple operators of the same precedence appear in an expression.
```python
result = 5 - 3 - 2
```
Both subtraction operators (-) have the same precedence. Since the associativity of the subtraction operator is left-to-right, the operations are performed as follows:
1. First, $5 - 3$ is evaluated, resulting in $2$.
2. Then, $2 - 2$ is evaluated, resulting in $0$.
So, the final value of result would be 0.
# Right to left Associativity (RtL)
> [!TLDR]
> Right-to-left associativity refers to the order in which operators of the same precedence are evaluated when they appear without parentheses to dictate the order explicitly. In a right-to-left associative context, operations are performed from right to left.
## Assignment Operator
Python's assignment operator (=) is right-to-left associative. This means when you have multiple assignment operators in a single expression, Python evaluates them from right to left.
```python
# Right-to-left associativity in assignment
a = b = c = 5
# The above is equivalent to:
# c = 5
# b = c
# a = b
print(a, b, c) # Output: 5 5 5
```
In this example, c is first assigned the value 5. Then, b is assigned the value of c, and a is assigned the value of b. The result is that a, b, and c all end up with the value 5.
## Exponentiation Operator
The exponentiation operator (\*\*) in Python is also right-to-left associative, which is particularly noticeable when chaining exponentiation operations.
```python
# Right-to-left associativity in exponentiation
result = 2 ** 3 ** 2
# The above is equivalent to:
# 2 ** (3 ** 2)
# 2 ** 9
# 512
print(result) # Output: 512
```
Here, 3 \*\* 2 is evaluated first, resulting in 9. Then, 2 \*\* 9 is evaluated, resulting in 512. If the operation were left-to-right associative, the calculation would proceed as (2 \*\* 3) \*\* 2, which would yield 64 instead.
# Chaining
![[operator_precedence_python__special_002.png]]
> [!TLDR] Advantages of Chaining (R: Piping)
> **Readability**: Chained comparisons are easier to understand at a glance.
> **Conciseness**: Chaining reduces the verbosity of your code, making complex conditions simpler and more straightforward
> **Maintainability**: With fewer repetitive variable names and operators, it's easier to modify your conditions later without introducing errors
## Chaining Comparisons
Python comparison operators (<, <=, >, >=, !=, \==) can be chained, meaning you can write expressions like $a \lt b \leq c$ without needing parentheses.
This is unique regarding associativity because Python evaluates chained comparisons differently than other languages. Instead of evaluating them as $(a \lt b) \, \text{and} \, (b \leq c)$, Python evaluates each comparison concerning the objects being compared. So, $a \lt b \leq c$ effectively checks if $a$ is less than $b$ and $b$ is less than or equal to $c$ without evaluating $b$ twice.
### Checking if a Number is Within a Range
Let's say you want to check if a number x is between 5 and 10 (inclusive). Instead of writing two separate comparisons and combining them with an and operator like this:
```python
x = 7
if x >= 5 and x <= 10:
print("x is between 5 and 10")
```
You can chain the comparisons like this:
```python
x = 7
if 5 <= x <= 10:
print("x is between 5 and 10")
```
### Explanation First Expression
$x \geq 5 \, \text{and} \, x \leq 10$ : This uses the traditional approach with the and operator to combine two separate comparisons. It explicitly checks if $x$ is greater than or equal to $5$ and if $x$ is less than or equal to $10$.
### Chained Comparison
$x \leq x \leq 10$: This is the chained comparison. It's more concise and arguably more readable. The expression reads almost like natural language:
If $5$ is less than or equal to $x$ and $x$ is less than or equal to $10$.
# Lambda Function
> [!TLDR]
> Lambda functions in Python are small, anonymous functions defined using the lambda keyword. They can have any number of arguments but only one expression, the result of which is the return value of the function.
Regarding precedence, lambda expressions have one of the lowest precedences. This means that operations within the lambda's arguments and the lambda's body are evaluated before the lambda itself is considered as a whole unit.
Because of its low precedence, a lambda function can be used in a context where its definition and execution do not interfere with the surrounding expressions unless explicitly combined with other operations with even lower precedence.
## Simple lambda Function
```python
result = lambda x, y: x + y
print(result(5, 3)) # Output: 8
```
The lambda function above takes two arguments $x$ and $y$, and returns their sum. The definition of the lambda function itself
$\text{lambda x, y:} \, x + y$
is straightforward, and its low precedence means that you don't need to worry about the operation $x + y$ being misinterpreted as part of a larger expression when defining the lambda.
## More advanced lambda Function
```python
action = (lambda x: (x % 2 and 'odd' or 'even')) # Parentheses for clarity
print(action(4)) # Output: even
```
The lambda function checks if a number is odd or even. The expression inside the lambda function makes use of logical operations with higher precedence
%,
and
or
that are evaluated before the lambda function is fully defined.
The precedence of lambda mainly affects how it is combined with other operations or functions in complex expressions. In practice, lambda functions are often used straightforwardly, such as arguments to higher-order functions like **map()**, **filter()**, and **sorted()**, where the syntax naturally isolates the precedence concerns.
# Some remaining Operators
![[operator_precedence_some_remaining_operators__577093969.png]]
## Unary operators
**+x, -x, ~x** indicate positive values, negate values, or flip bits, respectively.
## Bitwise
> [!multi-column]
>
>> [!NOTE] Shift operators
>> **<<, >>** shift the bits of the number to the left or right.
>
>> [!NOTE] AND
>> **&** performs bitwise AND on the bits of the numbers.
> [!multi-column]
>
>> [!NOTE] XOR
>> **^** performs bitwise XOR on the bits of the numbers.
>
>> [!NOTE] OR
>> **|** (vertical line) performs bitwise OR on the bits of the numbers.
## Logicals
> [!multi-column]
>
>> [!NOTE] NOT
>> **not** returns True if the operand is False and vice versa.
>
>> [!NOTE] AND
>> **and** returns True if both operands are true.
>
>> [!NOTE] OR
>> **or** returns True if at least one of the operands is true.
# Example
The expression you provided involves several operators, and understanding how each is evaluated is key to understanding the entire expression. Python follows specific rules for operator precedence, which determine the order in which the parts of the expression are processed.
Here’s the expression:
```python
x > y and x - y >= 2 or x + y == 1 and not x * y > 25
```
## Operator Precedence in Python
1. **Parentheses ()**: First priority, but not explicitly present in your expression.
2. **Arithmetic Operators** : `*`, `+`, `-`
3. **Comparison Operators**: `>`, `==`, `>=`
4. **Logical NOT**: `not`
5. **Logical AND**: `and`
6. **Logical OR**: `or`
Using these rules, let's break down your expression step-by-step:
## Step-by-Step Evaluation
### 1. Arithmetic Operations
$x - y$: Subtraction
$x + y$: Addition
$x * y$: Multiplication
The expression can be rethought as:
```python
x > y and (x - y) >= 2 or (x + y) == 1 and not (x * y) > 25
```
### 2. Comparison Operations
> [!multi-column]
>
>> [!BLANK]
>> $x \gt y$
>
>
>> Checks if $x$ is greater than $y$
> [!multi-column]
>
>> [!BLANK]
>> $(x - y) \geq 2$
>
>
>> Compares the result of $x - y$ to $2$
> [!multi-column]
>
>> [!BLANK]
>> $(x + y) \, \text{== 1}$
>
>
>> Checks if the sum of $x$ and $y$ equals $1$
> [!multi-column]
>
>> [!BLANK]
>> $(x * y) \gt 25$
>
>
>> Checks if the product of $x$ and $y$ is greater than $25$
This gives us:
```python
x > y and (x - y) >= 2 or (x + y) == 1 and not (x * y > 25)
```
### 3. Logical NOT
$\text{not} \, (x * y \gt 25)$: Evaluates whether $x * y \gt 25$ is False
### 4. Logical AND
> [!multi-column]
>
>> [!BLANK]
>> $x \gt y \, \text{and} \, (x - y) \geq 2$
>
>
>> Evaluates to True if both $x \gt y$ and $(x - y) \geq 2$ are True
> [!multi-column]
>
>> [!BLANK]
>> $(x + y) \, \text{== 1 and not} \, (x *y \gt 25)$
>
>
>> Evaluates to True if both $(x + y) \, \text{== 1}$ and
>> $\text{not} \, (x * y \gt 25)$ are True
### 5. Logical OR
Connects the two and operations:
```python
(x > y and (x - y) >= 2) or ((x + y) == 1 and not (x * y > 25))
```
This entire expression evaluates to True if either the first and condition or the second and condition evaluates to True.
## Conclusion
Thus, the overall logic of the expression can be summarized as: The expression evaluates to True if either x is more than y and the difference is at least 2, or the sum of x and y equals 1 and the product does not exceed 25. This step-by-step breakdown adheres to Python's rules of operator precedence, ensuring that operations are evaluated in the correct order for accurate results.
# Exercises
Here are 10 exercises involving various Python operators. Each exercise contains an expression combining multiple types of operators for you to evaluate step-by-step.
These exercises cover a mix of arithmetic, comparison, and logical operators, requiring careful consideration of operator precedence to solve correctly. You can use these to practice or test understanding of how Python evaluates complex expressions.
## 1
```python
a > b or a + b <= 20 and not a - b * 2 > 5
```
## 2
```python
x <= y and x ** 2 > 25 or x % y != 0 and not x * 2 < y
```
## 3
```python
z / x > 3 and z % x == 0 or z ** 2 == 64 and not z - 3 < 5
```
## 4
```python
k != j or k - j == 10 and not k / 2 > 5 and j % 2 == 0
```
## 5
```python
m < n or m * 3 >= 15 and not m / n <= 1 and n + m == 20
```
## 6
```python
p >= q or p ^ 2 == q and not p * q < 30 or q - p == 2
```
## 7
```python
v ** 2 <= w or v + 10 > w and not v - w != 5 or w * 2 == 40
```
## 8
```python
t == s and t + s > 30 or t - 2 * s < 0 and not t / s > 3
```
## 9
```python
c < d and c ** 3 > 27 or c % d == 1 and not c * 4 <= d
```
## 10
```python
f >= e or f - e == 5 and not f / e >= 2 or e % 3 == 0
```
# Instructions for Step-by-Step Evaluation:
1. **Arithmetic Operators**: Solve any arithmetic first (`+`, `-`, `*`, `/`, `%`, `**`).
2. **Comparison Operators**: Apply comparison operators (`>`, `<`, `>=`, `<=`, `==`, `!=`).
3. **Logical NOT**: Evaluate any `not` conditions.
4. **Logical AND**: Process any `and` conditions.
5. **Logical OR**: Finally, solve any `or` conditions.