1/35
Comprehensive practice flashcards covering Python operators, precedence, Boolean logic, functions, variable scope, string slicing, control flow, loops, and list mutation.
How does Python's floor division operator (//) behave with negative numbers?
Floor division rounds toward negative infinity rather than toward zero; for example, −7//2 evaluates to −4, not −3.
What is the result of the expression −3∗∗2 in Python, and why?
The result is −9 because exponentiation (**) binds tighter than the unary minus and is evaluated as −(3∗∗2).
How does Python evaluate a chained comparison such as 3<5<7?
It evaluates both comparisons together as 3<5 and 5<7 at once.
What rule governs the sign of the result of a modulo operation (%) in Python?
The remainder is calculated as remainder=a−(a//b)×b, and its sign matches the sign of the divisor (b). For example, 11%−4 evaluates to −1.
What is the order of precedence among the logical operators not, and, and or?
The operator not is evaluated first, followed by and, and finally or (for example, a or b and c is parsed as a or (b and c)).
State De Morgan's laws as applied to Python Boolean logic.
not (p and q) is equivalent to (not p) or (not q), and not (p or q) is equivalent to (not p) and (not q).
How does short-circuit evaluation work for and and or expressions in Python?
and stops evaluating as soon as the first operand is False, while or stops evaluating as soon as the first operand is True; the right-hand operand is not evaluated if the left-hand operand already decides the outcome.
What are the primary operational differences between print(x) and return x inside a function?
print(x) displays x on the screen without terminating the function and cannot be stored in a variable, whereas return x immediately ends the function and hands x back to the caller to be stored or used.
What value does a function return if execution reaches the end without encountering a return statement?
It evaluates to None.
How are arguments matched to parameters during a Python function call?
Arguments are matched to parameters by position from left to right, regardless of what the variable names are called in the outer calling scope.
What causes an UnboundLocalError when accessing a variable inside a function?
An UnboundLocalError occurs when a variable is assigned anywhere within a function body (marking it local for the entire function), but is read before that local assignment takes place.
What is the last valid index of a string s, and what error is raised if you access s[len(s)]?
The last valid index is len(s)−1; attempting to access s[len(s)] raises an IndexError.
What does it mean that strings are immutable in Python?
Individual characters cannot be altered or assigned in place (e.g., s[0] = "x" raises a TypeError); a new string must be constructed instead using concatenation and slicing.
How many characters are produced by a standard slice s[a:b] where the step is positive?
It produces b−a characters because the stop position b is excluded from the slice.
What happens when a string slice extends past the string boundary (e.g., word[10:])?
The slice is automatically clipped to the bounds of the string and returns an empty string "" without raising an error.
What is the result of the slice s[2:5:-1], and why?
It returns the empty string "" with a length of 0 because a negative step moves backward, but index 2 is before index 5, meaning start, stop, and step point in incompatible directions.
In chained slicing, how is an expression like s[::2][1] evaluated on s = "abcdefghij"?
The first slice s[::2] produces the intermediate string 'acegi', and [1] selects index 1 of that newly created string, resulting in 'c'.
What is the LEGB rule for Python variable scope lookup?
Python searches for names in the following order: Local scope, Enclosing functions, Global scope, and Built-ins.
How can a Python function modify a variable defined at the global module level?
By declaring the variable with the global keyword inside the function (e.g., global counter) prior to assigning to it.
How does an if / elif / else block decide which branch to execute?
Conditions are tested sequentially from top to bottom; the first condition that evaluates to True executes its branch, and all subsequent branches in that chain are skipped.
Why does "apple" < "Banana" evaluate to False in Python?
String comparisons are case-sensitive and compare character-by-character based on ASCII/Unicode values, where all uppercase letters come before all lowercase letters (making 'B' < 'a').
Why does "10" < "9" evaluate to True in Python?
Because both operands are strings and are compared character-by-character from left to right; the comparison is resolved at the first character where "1" < "9" is True.
Why must the strictest condition come first in an if / elif / else grade or threshold chain?
Because the chain stops at the first True condition; placing a broader condition first (such as score >= 50 before score >= 80) intercepts values that satisfy both and prevents stricter branches from ever being reached.
When classifying words by both palindrome and matching bookends, why must the palindrome check precede the bookends check?
Every palindrome inherently has matching first and last characters (bookends); if the bookends check came first, it would match all palindromes and make the palindrome branch unreachable.
What is the difference between iterating with for ch in s: versus for i in range(len(s)):?
for ch in s: iterates over each character directly one per pass, whereas for i in range(len(s)): generates integer indices from 0 to len(s)−1, which is required when positions or adjacent characters are needed.
Why must a loop that checks adjacent string pairs s[i] == s[i + 1] iterate over range(len(s) - 1)?
Stopping at len(s)−1 ensures the final iteration accesses the last character via s[i + 1]; using range(len(s)) would cause i + 1 on the final pass to index past the end and trigger an IndexError.
What is the structural difference between out = out + ch and out = ch + out when building a string in a loop?
out = out + ch appends to the back, preserving the original character sequence; out = ch + out prepends each new character to the front, reversing the sequence.
What logic error occurs when an else: has_digit = False statement is placed inside a character validation loop?
The else branch resets the flag to False on every non-digit character, causing the flag to reflect only the state of the final character in the string rather than the entire string.
What are the three essential components required by every well-behaved while loop?
A start value initialized before the loop, a condition checked before each iteration, and an update inside the loop body that moves the state toward making the condition False.
What values and number of iterations are produced by range(4, 4)?
It produces no values and executes 0 iterations.
What is the fundamental distinction between variable assignment and list mutation in Python?
Assignment (L = [4, 5, 6]) re-binds a variable name to a new object, leaving other references to the original object unchanged; mutation (L[0] = 7 or L.append(x)) modifies the existing object in place, which is seen by all variables referencing that object.
How can an independent copy of a list L be created so that mutations do not affect the original list?
By using L.copy() or the full slice L[:].
If a function assigns L[0] = 8 and then L = [1, 2, 3] to a parameter list, how is the caller's list affected?
The caller's list is mutated to have 8 at index 0, but the subsequent assignment L = [1, 2, 3] merely points the local parameter name to a new list and does not overwrite the caller's list.
In a loop for num in L: building unique even numbers, why is if num % 2 == 0 and num not in L: a logic bug?
Because num is drawn directly from L, it is always in L, making num not in L always False; the condition should check whether num not in evens (the accumulator list).
Why should an even_average(L) function guard against division by zero using if count == 0: instead of if total == 0:?
Valid lists of even numbers can sum to zero (such as [-2, 2], where total == 0 but count == 2); checking count == 0 specifically prevents a ZeroDivisionError on empty lists or lists containing no even numbers.
What happens if code calls L.append(num) on a list L inside a for num in L: loop?
It creates an infinite loop because new elements are continuously added to the end of the list being traversed, preventing the loop from reaching the end under normal execution.