7 Operators
7.1 The Wall
AI gave you a calculation that used // and % and you thought // was a comment. It was not. It was integer division. The result was wrong because you did not know what the operators did, so you could not tell whether AI had used the right ones.
In another case, AI wrote if x and y > 10: and you assumed it checked whether both x and y were greater than 10. It did not. It checked whether x was truthy and y was greater than 10. Subtle, silent, wrong.
This chapter fixes that.
7.2 Thinking Session
7.2.1 Getting Oriented
What operators does Python have beyond the basic +, -, *, /? I keep seeing //, %, **, and, or, not, ==, !=, is, in, can you organise them into categories and explain when each one is used? Focus on the ones that AI uses most often in generated code.
Your AI should group them: arithmetic (+, -, *, /, //, %, **), comparison (==, !=, <, >, <=, >=), logical (and, or, not), membership (in, not in), and identity (is, is not). If it lists bitwise operators, you can skip those for now.
7.2.2 Go Deeper
What is the difference between / and // in Python? And between == and is? These confuse me when I see them in AI-generated code. Give me examples where using the wrong one causes bugs.
/ gives a float (7 / 2 is 3.5), // gives an integer (7 // 2 is 3). == checks value equality, is checks identity (same object in memory). The classic trap: x == None works but x is None is correct. AI usually gets this right, but not always.
How does Python evaluate compound conditions? What does if x and y > 10 actually check? And what about if x or y? I want to understand operator precedence in conditions because AI writes these frequently.
7.2.3 Challenge It
What does each of these evaluate to, and why?
10 / 3
10 // 3
10 % 3
2 ** 10
"hello" * 3
"py" in "python"
not ""
True + True10 / 3 is 3.333..., 10 // 3 is 3, 10 % 3 is 1 (remainder). 2 ** 10 is 1024 (exponentiation). "hello" * 3 is "hellohellohello" (string repetition). "py" in "python" is True (substring check). not "" is True (empty string is falsy). True + True is 2 (booleans are integers).
7.2.4 What You Should Have Learned
//is integer division,%is remainder,**is exponentiation==checks value,ischecks identity (useisfor None)andandorshort-circuit. They do not always evaluate both sidesinchecks membership in strings, lists, and dictionaries- Empty strings, zero, None, and empty collections are all falsy
7.3 The Gap
Operators are the glue in AI-generated code. Every condition, every calculation, every loop test uses them. Now when you see if count % 5 == 0: you know it checks whether count is a multiple of 5. When you see if name and len(name) > 0: you know the and short-circuits, if name is empty, it never checks the length.
In the Building Session, you will add smarter response logic to your chatbot based on message properties.
7.4 Building Session
7.4.1 The Spec
Make your chatbot respond differently based on message characteristics:
- Respond to questions (input contains “?”)
- Respond differently to long messages (more than 50 characters) vs short ones
- Track whether the user has asked any questions using a boolean
- Use
into check for keywords
7.4.2 Prompt It
Update my chatbot to v0.7. Add operator-based response logic:
- If the input contains “?”, treat it as a question and respond with “Good question! I’m still learning…”
- If the message is longer than 50 characters, respond with “That’s a lot to take in!”
- If the message contains “python” or “coding” (use
in), respond enthusiastically - Track a boolean
has_asked_questionthat becomes True when the user asks their first question - Use the modulo operator: every 5th message, add “(milestone!)” to the response
Keep the existing features from v0.6.
7.4.3 Read the Code
Your AI will produce something like this:
"""PyBot v0.7: Operator-based responses."""
BOT_NAME = "PyBot"
VERSION = "0.7"
user_name = input(f"{BOT_NAME}: What's your name? ").strip()
while not user_name:
user_name = input("Please enter your name: ").strip()
print(f"Hello, {user_name}! Type 'quit' to exit, 'help' for commands.")
message_count = 0
has_asked_question = False
while True:
user_input = input(f"{user_name}: ").strip()
if not user_input:
print(f"{BOT_NAME}: Type something! Try 'help'.")
continue
if user_input.lower() == "quit":
print(f"{BOT_NAME}: Goodbye, {user_name}!")
break
message_count += 1
milestone = " (milestone!)" if message_count % 5 == 0 else ""
if "?" in user_input:
has_asked_question = True
response = "Good question! I'm still learning..."
elif "python" in user_input.lower() or "coding" in user_input.lower():
response = "I love that topic!"
elif len(user_input) > 50:
response = "That's a lot to take in!"
else:
response = f"You said '{user_input}'"
print(f"{BOT_NAME}: {response}{milestone}")"?" in user_input uses the in operator for substring check. message_count % 5 == 0 uses modulo to detect every 5th message. has_asked_question = True is a boolean flag. It starts False and flips once. The or in the keyword check means either match triggers the response.
7.4.4 Stretch It
Add a “stats” command that shows: total messages, whether any questions have been asked (True/False), and the average message length (total characters // message count).
7.5 Your Chatbot So Far
- Ch 1-2: Basic loop, structure, comments
- Ch 3-4: Type recognition, name memory, message count
- Ch 5-6: Formatted output, input validation, help
- Ch 7: Question detection, keyword matching, milestones
7.6 Quick Reference
# Arithmetic
7 / 2 # 3.5 (float division)
7 // 2 # 3 (integer division)
7 % 2 # 1 (remainder)
2 ** 10 # 1024 (exponentiation)
# Comparison
x == y # equal
x != y # not equal
x is None # identity (use for None)
# Logical
x and y # both true (short-circuits)
x or y # either true (short-circuits)
not x # negation
# Membership
"py" in "python" # True
5 in [1, 2, 3, 4, 5] # True
"key" in my_dict # True (checks keys)
# Falsy values
# False, 0, 0.0, "", [], {}, None