DEV Community

Cover image for Python Operators and Conditionals at the Airport Check-in Desk
David Mwandairo
David Mwandairo

Posted on

Python Operators and Conditionals at the Airport Check-in Desk

Zuri is flying to Lisbon. Her suitcase is full, the airline allows 23 kg, and she has no idea what the bag weighs. At the desk, an agent will put it on a scale and make a decision in about two seconds: pass it, charge for it, or send her away to repack.

That agent runs a small program in their head. It adds up weights, compares the total to a limit, combines a few yes/no questions, and picks one of three outcomes. Python does the same work with two tools: operators, which calculate and compare, and conditionals, which choose what happens next.

This article builds the agent's program one piece at a time. Each snippet was run on Python 3.12, and each output block shows what the terminal printed.

Arithmetic operators: weighing the bag

Python has seven arithmetic operators. Five behave like the keys on a phone calculator. Two, // and %, do work a calculator hides.

Operator Name At the desk
+ addition add up everything in the bag
- subtraction room left before the limit
* multiplication six shirts at 350 g each
/ true division grams to kilograms (always gives a decimal)
// floor division how many whole items still fit
% remainder (modulo) what is left after that
** power volume of a cube-shaped packing box

Zuri weighs her things in grams. Whole numbers keep the arithmetic clean, a habit worth copying whenever the quantities allow it:

# Everything in grams, so the numbers stay whole
empty_bag = 3500
shirts = 6
shirt = 350
shoes = 1200
laptop = 2100
limit = 23000

total = empty_bag + shirts * shirt + shoes + laptop
spare = limit - total
more_shirts = spare // shirt
left_over = spare % shirt

print("Packed weight:", total, "g")
print("Spare room:", spare, "g")
print("Extra shirts that fit:", more_shirts)
print("Gap after that:", left_over, "g")
print("Packed weight in kilograms:", total / 1000)
Enter fullscreen mode Exit fullscreen mode
$ python packing.py
Packed weight: 8900 g
Spare room: 14100 g
Extra shirts that fit: 40
Gap after that: 100 g
Packed weight in kilograms: 8.9
Enter fullscreen mode Exit fullscreen mode

The bag weighs 3,500 + 6 × 350 + 1,200 + 2,100 = 8,900 g. That leaves 14,100 g of room. Dividing 14,100 by 350 gives about 40.3, and // keeps only the 40 whole shirts. The % operator gives the part that did not fit: 100 g. The two operators work as a pair. One counts the full units, the other reports the remainder.

The last line uses /, which always returns a decimal number, even when the division comes out even.

Floor division rounds toward negative infinity, not toward zero. Positive numbers hide this, and negative ones show it:

print("7 / 2   =", 7 / 2)
print("7 // 2  =", 7 // 2)
print("7 % 2   =", 7 % 2)
print("2 ** 10 =", 2 ** 10)
print("-7 // 2 =", -7 // 2)
print("-7 % 2  =", -7 % 2)
print("35 ** 3 =", 35 ** 3)
Enter fullscreen mode Exit fullscreen mode
$ python operators.py
7 / 2   = 3.5
7 // 2  = 3
7 % 2   = 1
2 ** 10 = 1024
-7 // 2 = -4
-7 % 2  = 1
35 ** 3 = 42875
Enter fullscreen mode Exit fullscreen mode

The answer to -7 // 2 is -4, not -3. The pair still holds together, because (a // b) * b + a % b always equals a: (-4 × 2) + 1 = -7. The last line is the volume in cubic centimetres of a packing cube 35 cm on each side.

Precedence: multiplication goes first

Python follows school arithmetic. Power goes first, then *, /, // and %, then + and -. A misplaced parenthesis changes the answer without any warning:

empty_bag = 3500
shirts = 6
shirt = 350

wrong = (empty_bag + shirts) * shirt
right = empty_bag + shirts * shirt

print("wrong:", wrong)
print("right:", right)
Enter fullscreen mode Exit fullscreen mode
$ python precedence.py
wrong: 1227100
right: 5600
Enter fullscreen mode Exit fullscreen mode

The wrong line adds the bag weight to the shirt count (3,500 + 6, a meaningless sum) and then multiplies by 350. The right line lets * run first, which is what Zuri meant. When you doubt the order, add parentheses. They cost nothing and show the next reader what you meant.

Comparison operators: asking the scale a question

A comparison asks a yes/no question and answers with True or False. Python has six: ==, !=, <, >, <=, >=.

A single = stores a value. A double == asks whether two values are equal. Confusing the two is the most common typo in the language, and we will watch Python catch it at the end.

Python also lets you chain comparisons the way you would write them on paper:

total = 8900
limit = 23000

print("total <= limit:", total <= limit)
print("total == limit:", total == limit)
print("total != limit:", total != limit)
print("0 < total <= limit:", 0 < total <= limit)
print("0.1 + 0.2 =", 0.1 + 0.2)
print("0.1 + 0.2 == 0.3:", 0.1 + 0.2 == 0.3)
print('"apple" < "banana":', "apple" < "banana")
print('"Banana" < "apple":', "Banana" < "apple")
Enter fullscreen mode Exit fullscreen mode
$ python comparisons.py
total <= limit: True
total == limit: False
total != limit: True
0 < total <= limit: True
0.1 + 0.2 = 0.30000000000000004
0.1 + 0.2 == 0.3: False
"apple" < "banana": True
"Banana" < "apple": True
Enter fullscreen mode Exit fullscreen mode

Line by line:

  1. 8900 <= 23000 is True. The bag is under the limit.
  2. 8900 == 23000 is False. It is not exactly at the limit.
  3. 8900 != 23000 is True. The mirror image of the line above.
  4. 0 < total <= limit is True. A chain reads like the inequality from a maths lesson. Python treats it as 0 < total and total <= limit, and it reads total only once.
  5. 0.1 + 0.2 prints as 0.30000000000000004. Computers store decimals in binary, and 0.1 has no exact binary form, so a tiny error creeps in.
  6. That error is why 0.1 + 0.2 == 0.3 is False. Avoid testing decimals for exact equality when they came from arithmetic. This is one reason Zuri weighed everything in whole grams.
  7. "apple" < "banana" is True. Text compares letter by letter, so a comes before b.
  8. "Banana" < "apple" is also True, which surprises people. Python compares character codes, and every capital letter has a lower code than every small letter. Convert text to one case before you compare it.

Logical operators: combining questions

One comparison rarely settles a decision. Zuri's carry-on must weigh under 7 kg and fit either under the seat or in the overhead bin. That is three questions joined together.

Python has three logical operators. and is true when both sides are true. or is true when at least one side is. not flips an answer. When they mix, not binds first, then and, then or.

carry_on = 6200
fits_under_seat = False
fits_in_bin = True

light_enough = carry_on <= 7000
fits_somewhere = fits_under_seat or fits_in_bin

print("Light enough:", light_enough)
print("Fits somewhere:", fits_somewhere)
print("Carry-on accepted:", light_enough and fits_somewhere)
print("Not under the seat:", not fits_under_seat)
Enter fullscreen mode Exit fullscreen mode
$ python logic.py
Light enough: True
Fits somewhere: True
Carry-on accepted: True
Not under the seat: True
Enter fullscreen mode Exit fullscreen mode

The carry-on weighs 6,200 g, so light_enough is True. It does not fit under the seat but it does fit in the bin, so or gives True for fits_somewhere. Both halves of the final and are True, so the bag is accepted. The last line shows not turning False into True.

Short-circuit evaluation

Python reads and from left to right and stops at the first False, because nothing on the right can change the result. The same applies to or, which stops at the first True. That makes and a guard:

total_g = 8900
bags = 0

print("Safe check:", bags != 0 and total_g / bags > 20000)
print("Unsafe check:", total_g / bags > 20000)
Enter fullscreen mode Exit fullscreen mode
$ python short_circuit.py
Safe check: False
Traceback (most recent call last):
  File "/home/you/short_circuit.py", line 5, in <module>
    print("Unsafe check:", total_g / bags > 20000)
                           ~~~~~~~~^~~~~~
ZeroDivisionError: division by zero
Enter fullscreen mode Exit fullscreen mode

Suppose a bag count of zero slips in. In the safe check, bags != 0 is False, so Python never evaluates the division on the right, and the program prints False. In the unsafe check, Python tries to divide by zero and stops with a ZeroDivisionError. Put the cheap, protective test first, and let the risky one follow.

and and or return a value, not only True or False

First, a word on what "truthy" means. Python does not need a True or False to make a decision. In a condition, every value counts as one or the other. A value that counts as False is called falsy. A value that counts as True is called truthy. The falsy values are few: 0, 0.0, the empty string "", and False itself. Everything else is truthy, including negative numbers and any string with at least one character in it.

bags = 0
if bags:
    print("Bags counted:", bags)
else:
    print("No bags to check")

name = "Zuri"
if name:
    print("Hello,", name)
else:
    print("No name given")

change = -5
if change:
    print("-5 is truthy")
Enter fullscreen mode Exit fullscreen mode
$ python truthy.py
No bags to check
Hello, Zuri
-5 is truthy
Enter fullscreen mode Exit fullscreen mode

A bag count of 0 is falsy, so if bags: reads as "if there are any bags" and the else branch runs. A name with text in it is truthy. The surprise is -5: it is not zero, so it is truthy. Among numbers, only zero is falsy.

Now back to and and or. They hand back one of their operands, and they use truthiness to choose which. or gives back the first truthy value, or the last value if none is truthy. and gives back the first falsy value, or the last value if all are truthy. This gives a neat way to supply a default:

name = ""
print(name or "Passenger")

name = "Zuri"
print(name or "Passenger")
Enter fullscreen mode Exit fullscreen mode
$ python default_name.py
Passenger
Zuri
Enter fullscreen mode Exit fullscreen mode

The empty name is falsy, so or moves on to "Passenger". The name "Zuri" is truthy, so or stops there and returns it.

The bug nearly every beginner writes once

Zuri wants to know what to pack. She writes what she would say aloud: "if the city is Lisbon or Porto, take a light jacket." She is going to Oslo:

city = "Oslo"

if city == "Lisbon" or "Porto":
    print("Pack a light jacket")
else:
    print("Pack a warm coat")

if "Porto":
    print("A non-empty string counts as True")

if city == "Lisbon" or city == "Porto":
    print("Pack a light jacket")
else:
    print("Pack a warm coat")
Enter fullscreen mode Exit fullscreen mode
$ python jacket.py
Pack a light jacket
A non-empty string counts as True
Pack a warm coat
Enter fullscreen mode Exit fullscreen mode

Oslo is cold, and the first check still says to pack a light jacket. Python reads city == "Lisbon" or "Porto" as (city == "Lisbon") or ("Porto"). The left side is False, so or moves on to "Porto", a non-empty string, which is truthy. The condition passes for every city on Earth. The second if proves the point: a bare non-empty string passes as True. The fix is the third block, where each side of the or makes its own full comparison.

if, elif, else: choosing an outcome

A conditional statement tells Python which block of code to run. Python tests the conditions from top to bottom. It runs the first block whose condition is true, skips the rest, and moves on. The else block runs only if nothing above it matched. Exactly one block runs. Indentation marks which lines belong to which branch.

Here is the agent's decision. Up to 23 kg is free, 23 to 32 kg costs $12 for each extra kilo, and anything heavier is refused. Zuri's brother Baraka has a 26 kg bag:

weight_kg = 26

if weight_kg <= 23:
    print("Free")
elif weight_kg <= 32:
    extra = weight_kg - 23
    print("Extra kilos:", extra)
    print("Fee in dollars:", extra * 12)
else:
    print("Refused: repack")
Enter fullscreen mode Exit fullscreen mode
$ python check_bag.py
Extra kilos: 3
Fee in dollars: 36
Enter fullscreen mode Exit fullscreen mode

Trace it. Is 26 at most 23? No. Is it at most 32? Yes, so Python works out 26 - 23 = 3 extra kilos, prints the fee of 3 × 12 = 36, and never looks at else. Change the first line and run the script again to see the other branches:

# weight_kg = 18
$ python check_bag.py
Free

# weight_kg = 23
$ python check_bag.py
Free

# weight_kg = 32
$ python check_bag.py
Extra kilos: 9
Fee in dollars: 108

# weight_kg = 35
$ python check_bag.py
Refused: repack
Enter fullscreen mode Exit fullscreen mode

Note the boundaries. A bag of exactly 23 kg is free, and one of exactly 32 kg still pays, because both tests use <=. Whether the limit itself counts as in or out is a decision, and the operator you choose makes it.

The second test does not say "more than 23 and at most 32". It can say less, because by the time Python reaches it, the first test has already failed. The order of the tests carries information. Swap two of them and the program changes meaning:

weight_kg = 26

if weight_kg <= 32:
    extra = weight_kg - 23
    print("Extra kilos:", extra)
    print("Fee in dollars:", extra * 12)
elif weight_kg <= 23:
    print("Free")
else:
    print("Refused: repack")
Enter fullscreen mode Exit fullscreen mode
# weight_kg = 26
$ python broken_check.py
Extra kilos: 3
Fee in dollars: 36

# weight_kg = 18
$ python broken_check.py
Extra kilos: -5
Fee in dollars: -60
Enter fullscreen mode Exit fullscreen mode

The 26 kg bag still gets the right answer, which is how this bug survives testing. The 18 kg bag does not: it is charged minus $60. The test weight_kg <= 32 is true for every light bag, so the chain stops there and the free case never gets its turn.

The rule: when you test with < or <=, start with the smallest limit. When you test with > or >=, start with the largest.

elif is not the same as a second if

A chain of elif picks one winner. A row of separate if statements checks each condition on its own, so more than one block can run. Both forms are correct. They answer different questions:

weight_kg = 30

print("Two separate if statements:")
if weight_kg > 23:
    print("  over the free limit")
if weight_kg > 25:
    print("  over the warning line")

print("One if/elif chain:")
if weight_kg > 25:
    print("  over the warning line")
elif weight_kg > 23:
    print("  over the free limit")
Enter fullscreen mode Exit fullscreen mode
$ python if_vs_elif.py
Two separate if statements:
  over the free limit
  over the warning line
One if/elif chain:
  over the warning line
Enter fullscreen mode Exit fullscreen mode

A 30 kg bag is over both lines. The separate if statements report both. The chain stops at the first match and reports one. Use separate if statements when the cases can overlap and you want every match. Use elif when the cases compete and only one should apply.

Putting it together: the check-in desk

Now the full program for one passenger. Frequent flyers get 5 extra kilos on the checked bag. Each passenger has a checked bag and a carry-on, and the desk reports the fee and whether the passenger can move on to security. It uses all three kinds of operator and every form of if.

name = "Zuri"
checked_kg = 18
carry_on_kg = 6
is_member = False

free_kg = 23
max_kg = 32
fee_per_kg = 12
carry_on_max_kg = 7
member_bonus_kg = 5

allowed_kg = free_kg
if is_member:
    allowed_kg = free_kg + member_bonus_kg

extra_kg = checked_kg - allowed_kg
refused = checked_kg > max_kg
carry_ok = carry_on_kg <= carry_on_max_kg

print("Passenger:", name or "Unnamed")
print("Checked bag allowance:", allowed_kg, "kg")

if refused:
    print("Checked bag: refused, repack")
elif extra_kg > 0:
    print("Checked bag: extra", extra_kg, "kg, fee in dollars:", extra_kg * fee_per_kg)
else:
    print("Checked bag: free")

if carry_ok:
    print("Carry-on: OK")
else:
    print("Carry-on: too heavy by", carry_on_kg - carry_on_max_kg, "kg")

if not refused and carry_ok:
    print("Result: go to security")
else:
    print("Result: fix the problems above first")
Enter fullscreen mode Exit fullscreen mode
$ python checkin.py
Passenger: Zuri
Checked bag allowance: 23 kg
Checked bag: free
Carry-on: OK
Result: go to security
Enter fullscreen mode Exit fullscreen mode

Zuri's bag is under the limit and her carry-on is under 7 kg, so she goes through. To see the other branches, change the first four lines and run the script again. Baraka has a 26 kg bag and no membership:

# name = "Baraka", checked_kg = 26, carry_on_kg = 5
$ python checkin.py
Passenger: Baraka
Checked bag allowance: 23 kg
Checked bag: extra 3 kg, fee in dollars: 36
Carry-on: OK
Result: go to security
Enter fullscreen mode Exit fullscreen mode

Baraka pays for three extra kilos, and a fee is a cost, not a failure, so he still goes to security. Next comes Imani, a member with the same 26 kg bag but an 8 kg carry-on. Last is a passenger who left the name blank and brought a 35 kg bag:

# name = "Imani", checked_kg = 26, carry_on_kg = 8, is_member = True
$ python checkin.py
Passenger: Imani
Checked bag allowance: 28 kg
Checked bag: free
Carry-on: too heavy by 1 kg
Result: fix the problems above first

# name = "", checked_kg = 35, carry_on_kg = 4
$ python checkin.py
Passenger: Unnamed
Checked bag allowance: 23 kg
Checked bag: refused, repack
Carry-on: OK
Result: fix the problems above first
Enter fullscreen mode Exit fullscreen mode

Imani's allowance is 28 kg, so her 26 kg bag is free, but her carry-on is one kilo over, so she must fix that first. The blank name falls back to "Unnamed" through or. At 35 kg, the bag is over the 32 kg maximum and gets refused.

Each tool did its own job. Arithmetic (+, -, *) produced the extra kilos and the fee. Comparison (<=, >) turned numbers into yes/no answers. Logic (not, and, or) combined those answers: not refused and carry_ok is the whole test for "go to security". The if/elif/else blocks turned the answers into actions.

What Python says when you slip

I promised to show what happens when = replaces ==:

weight_kg = 23
if weight_kg = 23:
    print("exactly at the limit")
Enter fullscreen mode Exit fullscreen mode
$ python typo.py
  File "/home/you/typo.py", line 2
    if weight_kg = 23:
       ^^^^^^^^^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
Enter fullscreen mode Exit fullscreen mode

Python refuses to run the file and points at the exact expression. Recent versions even suggest the fix. The harder mistakes run without complaint: an or that is always true, a chain in the wrong order, a decimal compared with ==. No error message flags them. You find them by testing the edge cases, which is what the exercises below ask you to do.

Try it yourself

Copy checkin.py and change it.

  1. Set checked_kg to exactly 23 and predict what the program prints, then run it. Now change one operator so that 23 kg costs a fee, and check that nothing else breaks.
  2. Add a rule: a carry-on counts as too heavy above 7 kg, unless the passenger is a member, who may carry 10 kg. Combine and and or in one condition, and add parentheses to show your intent.
  3. Set checked_kg to 32 and carry_on_kg to 7. Which messages do you expect? Run it and check whether the order of your if/elif chain gives them.

If you build something with these tools, such as a parking meter, a bus fare calculator or a school canteen till, tell me in the comments what decision it makes. And tell me which of the bugs above you have already written yourself.

Top comments (0)