Python Expressions: Intermediate

Dropbox famously reduced its Python codebase from 150,000 lines to 90,000 lines by systematically replacing verbose patterns with cleaner syntax, cutting 40% of their code while making it more readable and faster to maintain. The engineers who led that effort leaned heavily on list comprehensions, conditional expressions, and other expressive Python idioms that let a single line replace five. When a company the size of Dropbox can delete 60,000 lines of code and end up with a better product, it demonstrates that elegant syntax is not just aesthetically pleasing but a genuine engineering advantage. This lesson teaches you the clean syntax patterns that make that kind of transformation possible.

Type Conversions

Daily Life
Interviews

Switch between types without losing data

Remember from the beginner lesson that every value has a type? An integer like 42 is different from a string like "42", even though they look similar. Sometimes you need to convert between these types.

Why Convert Between Types?

Data doesn't always arrive in the format you need. Here are common situations where type conversion is essential:
User input
Always arrives as text, even when users type a number.
Files (CSV, JSON)
Store everything as text strings that need parsing into numbers.
API responses
Return data as strings that your code must convert to usable types.
Display output
Numbers must become strings before you can embed them in messages.
For example, if a user types "25" into an age field, your program receives the string "25", not the number 25. To check if they're old enough to vote, you need to convert that string to a number first.

The Conversion Functions

Python provides built-in functions that convert values from one type to another. Each function is named after the type it creates:
int()float()str()bool()
int()
To integer
Whole numbers, truncates
float()
To decimal
Adds decimal precision
str()
To text
Text for display output
bool()
To boolean
True or False from value

int() - Convert to Integer

Takes a value and returns a whole number. It truncates decimal points instead of rounding, and can convert strings that contain only digits.
Converting a string to an integer:
1user_input = "25"
2age = int(user_input)
3birth_year = 2024 - age
4print(f"Age: {age}, Born: {birth_year}")
>>>Output
Age: 25, Born: 1999
Now age contains the integer 25, not the string "25", so you can do math with it.
Converting a float to an integer removes the decimal part:
1print(int(3.9))
2print(int(3.1))
3print(int(-2.7))
>>>Output
3
3
-2
All three cut off the decimal portion. 3.9 becomes 3, not 4. This is truncation, not rounding.
TIP
If you need actual rounding, use round() instead: round(3.7) returns 4, while int(3.7) returns 3.

float(): Convert to Decimal

Creates a decimal number from integers or strings. Useful when you need precision or when working with division results.
1price_text = "19.99"
2price = float(price_text)
3print(price)
4
5whole_number = 42
6decimal_version = float(whole_number)
7print(decimal_version)
>>>Output
19.99
42.0
Now price is 19.99 (a number, not text). float(42) creates 42.0, useful when you need decimal behavior.

str() - Convert to String

Turns any value into its text representation. This is essential for displaying numbers in messages and required when combining text with numbers.
You can't concatenate strings with numbers directly. This causes an error:
1message = "Found " + 42 + " items"
Convert the number to text first:
1message = "Found " + str(42) + " items"
2print(message)
>>>Output
Found 42 items
Now message contains "Found 42 items". The str() function converts 42 to the string "42" so concatenation works.

bool() - Convert to Boolean

Converts any value to True or False. Python follows specific rules about what counts as "truthy" versus "falsy", which you will use constantly in conditions.
Python has clear rules about what values become True and what become False:
1print(bool(1))
2print(bool(0))
3print(bool(""))
4print(bool("hello"))
>>>Output
True
False
False
True

1 becomes True, 0 becomes False. Empty string "" becomes False, but any non-empty string becomes True.

When Conversions Fail

Not all conversions are possible. What happens if you try to convert the word "hello" to a number? Python doesn't know what number "hello" should become, so it raises an error:
1int("hello")
2int("12.5")
3float("abc")
All three crash with ValueError. Notice int("12.5") also fails because int() can't parse decimals from text. You'd need float() first, then int().
TIP
When processing external data (user input, files, APIs), always consider that the data might not be in the format you expect. Invalid data will crash your program unless you handle it.
Debug Challenge

> This code tries to convert the string "12.5" directly to an integer, but int() cannot parse decimals. Fix the conversion.

ValueError: int() cannot parse "12.5" because it contains a decimal point

The two-step conversion int(float(text)) is a common pattern when data arrives as a decimal string but you need a whole number. float() parses the decimal, then int() truncates it.

Chaining conversion functions like this is readable and explicit. Each conversion step has a clear purpose, making the intent obvious to anyone reading the code.
Now try selecting different conversion functions to see how Python transforms the same string value.
Fill in the Blank

> Pick a conversion function to see how Python transforms the string "3.14" into a different type.

text = "3.14"
result = (text)
print(result, type(result))
The fact that bool("False") returns True surprises many beginners. bool() checks whether a string is non-empty, not whether it spells out a true value.
Type conversion is a gateway skill. Once you can reliably move data between types, you can handle real-world inputs from files, APIs, and user prompts with confidence.
TIP
When in doubt about what a conversion will produce, test it in the Python REPL or use type() to inspect the result. There is no penalty for experimenting.

Comparison Operators

Daily Life
Interviews

Test conditions accurately in your code

Programs need to make decisions. Should this user be granted access? Is the account balance sufficient? Has the deadline passed? These are all yes-or-no questions, and comparison operators let you ask them.

What is a Comparison?

A comparison is an expression that asks a question about two values. The answer is always a boolean: either True or False. Think of it as asking the computer a yes-or-no question.

1age = 25
2print(age > 18)
>>>Output
True

The expression age > 18 asks: "Is age greater than 18?" Since age is 25, the answer is True.

Six Comparison Operators

Python has six comparison operators. Each one asks a different type of question:
== Equal to
Are these two the same?
!= Not equal to
Are these two different?
> < Greater / Less
Which side is the larger?
>= <= Or equal to
Greater or equal, or less
Checking if two values are exactly the same:
1score = 100
2
3print(score == 100)
4print(score == 50)
5print(score != 50)
>>>Output
True
False
True

The first returns True, the second False, the third True.

Remember from the beginner lesson: = is assignment (storing a value), while == is comparison (asking if equal). This is one of the most common mistakes beginners make.

Debug Challenge

> This if-statement has a space in the middle of the equality operator. Remove the extra tile to fix it.

SyntaxError: invalid syntax

Greater-than and less-than operators compare which side is larger or smaller:
1temperature = 75
2
3print(temperature > 100)
4print(temperature < 100)
5print(temperature > 32)
>>>Output
False
True
True

The >= and <= operators include the boundary value. This "or equal" distinction matters in real applications like age verification:

1age = 18
2
3print(age >= 18)
4print(age > 18)
5print(age <= 18)
>>>Output
True
False
True

Returns True, False, and True. Notice >= is True when age is exactly 18, but > is False. The "or equal" part matters!

Comparing Strings

You can compare strings too. Python compares them alphabetically, character by character. This is called lexicographic ordering:
1print("apple" < "banana")
2print("cat" == "cat")
3print("dog" > "cat")
>>>Output
True
True
True
All three are True. "apple" comes before "banana" alphabetically.
String comparison is case-sensitive:
1print("Cat" == "cat")
2print("Apple" < "apple")
>>>Output
False
True
First is False (different case). Second is True (uppercase has lower character code than lowercase).

Storing Comparison Results

You can store comparison results in variables:
1password_length = 12
2
3is_long_enough = password_length >= 8
4has_minimum_length = password_length >= 6
5
6print(is_long_enough)
7print(has_minimum_length)
>>>Output
True
True
Both variables contain True. You can use these boolean variables later whenever you need to check the condition.

Logical Operators

Daily Life
Interviews

Combine conditions with and, or, and not

Real-world decisions are rarely simple. "Can this user access the file?" might depend on multiple factors: Are they logged in? Do they have permission? Is the file not locked? Logical operators let you combine multiple conditions into one decision.

The Three Logical Operators

Python has three logical operators. Think of them as ways to connect yes-or-no questions:
and
Both conditions must be True for the result to be True
or
At least one condition must be True for the result to be True
not
Flips True to False, and False to True

The "and" Operator

The and operator requires BOTH conditions to be True. If either one is False, the whole expression is False. Think of it as a strict rule: everything must pass.

Imagine a nightclub that requires guests to be 21+ AND have valid ID. Both conditions must be met:
1age = 25
2has_id = True
3
4can_enter = age >= 21 and has_id
5print(can_enter)
>>>Output
True
can_enter is True because BOTH conditions are True.
1print(True and True)
2print(True and False)
3print(False and True)
4print(False and False)
>>>Output
True
False
False
False
Only the first is True. All others are False because at least one side is False.

The "or" Operator

The or operator requires AT LEAST ONE condition to be True. It's less strict than "and". Think of it as: if any option works, we're good.

Imagine a building where you can enter if you're an employee OR a registered visitor:
1is_employee = False
2is_registered_visitor = True
3
4can_enter = is_employee or is_registered_visitor
5print(can_enter)
>>>Output
True
can_enter is True because at least one condition is True.
1print(True or True)
2print(True or False)
3print(False or True)
4print(False or False)
>>>Output
True
True
True
False
Only the last is False. All others are True because at least one side is True.

The "not" Operator

The not operator flips a boolean value. True becomes False, and False becomes True. It's like saying "the opposite of..."

If a user is blocked, you might want to check if they're NOT blocked:
1is_blocked = False
2can_post = not is_blocked
3print(can_post)
>>>Output
True
Since is_blocked is False, "not False" becomes True.
1age = 15
2is_adult = age >= 18
3is_minor = not is_adult
4
5print(is_adult)
6print(is_minor)
>>>Output
False
True
is_adult is False (15 is not >= 18), so is_minor is True.

Combining Operators

You can combine multiple logical operators to create complex conditions. But be careful about the order Python evaluates them:
01
not
Evaluated first. Flips a single boolean value before anything else.
02
and
Evaluated second. Combines two conditions with a strict "both must pass" rule.
03
or
Evaluated last. The most lenient check: only one side needs to be True.
This order can lead to unexpected results:
1a = True
2b = False
3c = True
4
5a or b and c

Because and has higher priority, this evaluates as a or (b and c), not (a or b) and c.

Use parentheses to make your intent clear:
1(a or b) and c
2a or (b and c)
These give different results! Parentheses make your intention explicit.
TIP
When you have more than two conditions, always use parentheses. Even if the default order happens to be what you want, parentheses make your code easier to read and less prone to bugs.

A Real-World Example

Let's say a user can access a premium feature if they're a paying subscriber AND not banned, OR if they're an administrator:
1is_subscriber = True
2is_banned = False
3is_admin = False
4
5can_access = (is_subscriber and not is_banned) or is_admin
6print(can_access)
>>>Output
True
The user can access the feature because they're a paying subscriber who isn't banned.
Fill in the Blank

> Python's and/or operators return actual values, not just True or False. Toggle between them to see which value gets picked.

x = 0
y = 5
result = x  y
print(result)
Logical operators form the backbone of every decision your program makes. Whether you are controlling access, validating input, or branching logic, you will reach for and, or, and not constantly.
Using parentheses when combining operators is always the right call. They cost nothing in performance and make the intent of complex conditions immediately clear.

Multiple Assignment

Daily Life
Interviews

Set several variables in one statement

Python has a convenient feature that lets you assign values to multiple variables in a single line. This makes certain patterns cleaner and more readable.

Assigning Multiple Vars

1x, y, z = 1, 2, 3
2name, age, city = "Maya", 28, "Austin"
3
4print(x, y, z)
5print(name, age, city)
>>>Output
1 2 3
Maya 28 Austin
The values on the right are matched up with the variables on the left, in order.

Swapping Values

In many languages, swapping requires a temporary variable. In Python:
1a = 10
2b = 20
3print("Before:", a, b)
4
5a, b = b, a
6print("After:", a, b)
>>>Output
Before: 10 20
After: 20 10
Python evaluates the right side first (b, a), then assigns to the left side. No temp variable needed.

Unpacking from Collections

You can "unpack" a tuple into separate variables:
1coordinates = (10, 20)
2x, y = coordinates
3print(x, y)
4
5quotient, remainder = divmod(17, 5)
6print(quotient, remainder)
>>>Output
10 20
3 2
Now x is 10 and y is 20. divmod(17, 5) returns (3, 2), so quotient is 3 and remainder is 2.
Pythonic
  • a, b = b, a
  • x, y = get_coordinates()
  • quotient, rem = divmod(17, 5)
Verbose
  • temp = a; a = b; b = temp
  • result = get_coordinates(); x = result[0]; y = result[1]
  • result = divmod(17, 5); quotient = result[0]; rem = result[1]
Fill in the Blank

> Python can swap two variables in one line. Compare simultaneous swap to step-by-step assignment to see why order matters.

a = 1
b = 2

print(a, b)
The simultaneous evaluation is what makes multiple assignment safe. Python builds the right-hand tuple first, then unpacks it, so no value is overwritten before it is read.
Unpacking from functions like divmod() or enumerate() follows the same principle. Any iterable on the right side can be unpacked into any matching number of variables on the left.
TIP
Multiple assignment is not just for swapping. Use it whenever a function returns multiple values, such as divmod(17, 5) returning both quotient and remainder in one call.

None and Identity

Daily Life
Interviews

Check for missing values the right way

Sometimes a variable needs to exist but doesn't have a meaningful value yet. Maybe you're waiting for data to arrive, or a search found nothing. Python has a special value for this: None.

What is None?

None is Python's way of representing "no value" or "nothing." It's not the same as zero (0 is a number). It's not the same as an empty string ("" is still a string). None means the complete absence of a value.

1result = None
2user = find_user_by_email("test@example.com")

You might use None as a placeholder, or a function might return None to indicate "not found."

Functions and None

In Python, if a function doesn't explicitly return a value, it automatically returns None. Consider a function that just prints something:

1def greet(name):
2 print("Hello, " + name)
3
4result = greet("Maya")
5print(result)
>>>Output
Hello, Maya
None

greet prints "Hello, Maya" but does not return anything, so result becomes None.

Checking for None

Use is to check for None:

1if result is None:
2 print("No result found")
3
4if user is not None:
5 print("Found user: " + user.name)

Why "is" Instead of "=="?

The == operator checks if two values are equal. The is operator checks if two variables refer to the exact same object in memory.

Do
  • result is None
  • value is not None
  • if user is None: handle()
Don't
  • result == None
  • value != None
  • if not user: handle()
1a = [1, 2, 3]
2b = [1, 2, 3]
3c = a
4
5print(a == b)
6print(a is b)
7print(a is c)
>>>Output
True
False
True

a == b is True (same values). a is b is False (different objects). a is c is True (same object).

TIP
Rule of thumb: Use is when checking for None. Use == when comparing values of regular types like numbers and strings.
Fill in the Blank

> None, 0, and "" are all falsy but they are not the same object. Pick an operator to see the difference.

x = None
result = x  0
print(result)

None is the correct signal for "no value here." Functions that search for something and fail, or optional parameters that were not provided, return or default to None.

The is None check is a universal Python convention. You will see it in standard library code, open-source projects, and production codebases across every domain.

TIP
Always check for None explicitly with is None rather than relying on truthiness. A result of 0 or an empty list is falsy but valid, and a truthiness check would incorrectly treat it as "no result".
PUTTING IT ALL TOGETHER

> You are a data analyst at Datadog building a Python script that reads daily pipeline metrics from an API and prints formatted diagnostic summaries to a shared log file. The script must coerce raw string inputs, compare thresholds, combine conditions, and unpack multiple return values in a single pass.

Type conversions like int() and float() coerce raw string metric values from the API response into numbers before any calculation.
Comparison operators such as > and <= check whether each metric crosses a warning or critical threshold before writing to the log.
Logical operators combine threshold checks so a line is only flagged when both latency is high and error rate exceeds the limit.
Multiple assignment unpacks paired values like latency, error_rate = parse(record) so both metrics are captured in one readable line.
KEY TAKEAWAYS
Use int(), float(), str(), bool() to convert between types
int() truncates decimals (3.9 becomes 3), use round() for actual rounding
Six comparison operators: == != < > <= >= - all return True or False
and requires both conditions True, or requires at least one True
not flips True to False and False to True
Use parentheses when combining multiple logical operators
Multiple assignment: a, b = 1, 2 and swap with a, b = b, a
None represents "no value" - check with is None, not == None

Python Expressions: Intermediate

Making decisions with data

Category
Python
Difficulty
intermediate
Duration
38 minutes
Challenges
0 hands-on challenges

Topics covered: Type Conversions, Comparison Operators, Logical Operators, Multiple Assignment, None and Identity

Lesson Sections

  1. Type Conversions (concepts: pyTypeConversion)

    Remember from the beginner lesson that every value has a type? An integer like 42 is different from a string like "42", even though they look similar. Sometimes you need to convert between these types. Why Convert Between Types? Data doesn't always arrive in the format you need. Here are common situations where type conversion is essential: For example, if a user types "25" into an age field, your program receives the string "25", not the number 25. To check if they're old enough to vote, you ne

  2. Comparison Operators

    Programs need to make decisions. Should this user be granted access? Is the account balance sufficient? Has the deadline passed? These are all yes-or-no questions, and comparison operators let you ask them. What is a Comparison? Six Comparison Operators Python has six comparison operators. Each one asks a different type of question: Checking if two values are exactly the same: Greater-than and less-than operators compare which side is larger or smaller: Comparing Strings You can compare strings

  3. Logical Operators

    Real-world decisions are rarely simple. "Can this user access the file?" might depend on multiple factors: Are they logged in? Do they have permission? Is the file not locked? Logical operators let you combine multiple conditions into one decision. The Three Logical Operators Python has three logical operators. Think of them as ways to connect yes-or-no questions: The "and" Operator Imagine a nightclub that requires guests to be 21+ AND have valid ID. Both conditions must be met: can_enter is Tr

  4. Multiple Assignment

    Python has a convenient feature that lets you assign values to multiple variables in a single line. This makes certain patterns cleaner and more readable. Assigning Multiple Vars The values on the right are matched up with the variables on the left, in order. Swapping Values In many languages, swapping requires a temporary variable. In Python: Python evaluates the right side first (b, a), then assigns to the left side. No temp variable needed. Unpacking from Collections You can "unpack" a tuple

  5. None and Identity

    What is None? Functions and None Checking for None Why "is" Instead of "=="?