Python Basics: Operators, Logic, Loops, Strings, Functions, Lists, Dictionaries and File I/O

Python Basics, Operators, Logic and Loops

Syntax and Reading Code

Variables such as x, y, value, word, text, n, i, total, and result are ordinary variable names, not Python commands. x=5 assigns or reassigns a value, while == compares equality. Python runs statements from top to bottom, expressions follow operator precedence, and chained methods run from left to right: s.lower().title().

  • # starts a comment that is ignored.
  • Indentation groups blocks of code.
  • : begins an if, for, while, or def block.
  • () is used for function calls and grouping.
  • [] is used for lists, indexing, and slicing.
  • {} is used for dictionaries, sets, and f-string placeholders.
  • .method() calls a method.
  • Quotes '...' or "..." create strings.

Python is case-sensitive: True, False, and None are capitalized, and x is not the same as X. An error stops execution unless it is handled.

Types and Casting

  • int: integer, such as 5.
  • float: decimal number, such as 5.0.
  • str: text, such as '5'.
  • bool: True or False.
  • None: absence of a value, with type NoneType.

type(x) returns the type. int(5.9) gives 5, and int(-5.9) gives -5 because it truncates toward 0. int('7') gives 7, but int('7.0') raises a ValueError. float('7') gives 7.0, and str(5) gives '5'. bool(x) tests truthiness.

input('prompt') always returns a string. Use int(input(...)) to get an integer or float(input(...)) to get a decimal number. '7'+str(3) gives '73', int('7')+3 gives 10, 'ha'*3 gives 'hahaha', and '7'+3 raises a TypeError. Adding an int and a float gives a float, so 3*2.0 gives 6.0. Note that True==1 and False==0, so booleans behave as numbers in calculations.

Truthiness

The following values are falsy: 0, 0.0, False, None, '', [], (), {}, and set(). Non-empty strings such as '0', 'False', and ' ', non-zero numbers including -1, and non-empty containers are truthy.

Printing and Formatting

  • print(a,b) adds a default space between values.
  • print(a,b,sep='@',end='!') changes the separator and ending.
  • print() prints a newline.
  • \n is a newline, \t is a tab, \\ is a backslash, and \' is a quote.
  • repr(s) displays escapes and quotes for inspection.

format(x,'.2f') returns a string with two decimals. The same result can be written as f'{x:.2f}'. Other useful patterns include f'{x:05d}' to zero-pad an integer to width 5 (18 becomes 00018), f'{x:>8}' to right-align, < to left-align, ^ to center, f'{x:.2e}' for scientific notation, and f'{x:,.2f}' for commas and two decimals.

'{} {}'.format(a,b) fills placeholders in order, and '{1} {0}'.format('a','b') gives 'b a'. The older %d, %f, and %s codes are for int, decimal, and string values. format(10/3,'.2f') gives the string '3.33'.

Arithmetic and Precedence

  • + addition, or string and list concatenation.
  • - subtraction.
  • * multiplication, or repetition.
  • / true division, which always returns a float: 4/2 gives 2.0.
  • // floor division, which rounds down toward negative infinity: 10//3 gives 3 and -9//4 gives -3. If a float is involved, the result is a float: 5.0//2 gives 2.0.
  • % remainder: 10%4 gives 2, 15%6 gives 3, and 17%5 gives 2.
  • ** exponent: 2**3 gives 8, 2**3**2 gives 512 (right-associative), (2**3)**2 gives 64, and -2**2 gives -4.

Dividing by zero with / or // raises a ZeroDivisionError. For positive b, the remainder satisfies a == (a//b)*b + (a%b), with the remainder ranging from 0 to b-1.

Operator precedence, from highest to lowest, is: parentheses, **, unary + and -, * / // %, + and -, comparisons (<, <=, >, >=, ==, !=, is, in), not, and, and or. Comparisons can be chained: a>b>c means (a>b) and (b>c).

Augmented assignment operators (+=, -=, *=, /=, //=, %=, **=) update the left variable: x+=y means x=x+y. Note that >= and <= are comparisons, not augmented assignments.

Booleans and Short-Circuit Evaluation

not x gives the opposite truthiness. and returns the first falsy operand, or the last operand if none is falsy. or returns the first truthy operand, or the last operand if none is truthy. Examples: 0 and 99 gives 0, 5 and 9 gives 9, 0 or 'yes' gives 'yes', and 5 or 9 gives 5.

Evaluation short-circuits: 0 and (1/0) gives 0 with no error, and 1 or unknown gives 1 with no error, but 0 or unknown raises a NameError. Two equal numeric literals are not guaranteed to share identity, so avoid using is for numeric equality.

Branches

In an if/elif/else chain, only the first matching branch executes. An elif is checked only if the earlier branches are false, and else is the catch-all branch. Separate if statements can each run. Indentation determines which else belongs to which if.

A ternary expression has the form A if condition else B. For example, with x=7, the code if x<5: print('Low') followed by elif x%2==1: print('Odd') and else: print('Other') prints Odd.

Loops

A for loop iterates over characters, lists, tuples, sets, dictionary keys, or range objects. A while loop repeats while its condition is truthy, so update the counter to avoid an infinite loop.

  • range(stop) produces 0 to stop-1.
  • range(start,stop[,step]) includes start and excludes stop; the default step is +1. range(2,10,3) gives 2, 5, 8; range(10,2,-3) gives 10, 7, 4.
  • range(5,3,+1) is empty (not an error), and range(5,3,-1) gives 5, 4.
  • step=0 raises a ValueError.

list(range(...)) displays the numbers, while range(...) alone shows a range object. len(range(...)) gives the number of generated values.

  • break exits the nearest loop immediately.
  • continue skips the rest of the current iteration and moves to the next.
  • pass does nothing; later statements still run.
  • return exits the function, not merely the loop.

In nested loops, break leaves only the inner loop. Using continue in a while loop before the counter increment causes an infinite loop. A for or while loop’s else block runs only if the loop completes without a break.

Common patterns include accumulators (total=0; total+=n, and product=1; product*=n) and sentinels (if input=='done': break). If total is checked after the addition, the value that crossed the threshold is preserved when breaking.

Round, Abs and ASCII

round(x[,ndigits]) rounds to a number of decimal places; n=-1 rounds to the nearest ten and n=-2 to the nearest hundred. Exact halfway values round to the nearest even number: round(2.5) gives 2, round(3.5) gives 4, and round(450.,-2) gives 400.0. Because of binary floating-point representation, round(2.675,2) gives 2.67.

abs(-5) gives 5, pow(2,3) gives 8, and divmod(10,3) gives (3,1). ord(ch) returns the code of a character, and chr(code) returns the character for a code. The space character ' ' has code 32 (not 0), digits '0' to '9' are 48 to 57, uppercase 'A' to 'Z' are 65 to 90, and lowercase 'a' to 'z' are 97 to 122. For example, chr(65) gives 'A' and ord('a')-ord('A') gives 32.

Strings compare left to right by Unicode code point, so uppercase sorts before lowercase ('A' < 'a' is True), and a shorter matching prefix sorts first ('Hell' < 'Hello'). min('cBaD') gives 'B' and min('PYTHON') gives 'H'.

Strings, Slicing and Classifiers

String Basics and Indexing

Strings are immutable and ordered, so s[0]='X' is not allowed. Spaces and punctuation count as characters. Indexing starts at 0, and negative indexes count from the right, with -1 the last character. For s='network', s[3] is 'w', s[-1] is 'k', and s[7] raises an IndexError.

Slicing

The slice syntax is seq[start:stop:step]. The start is included, the stop is excluded, and the step defaults to 1. A positive step moves right and needs start before stop; a negative step moves left and needs start after stop. A step of 0 raises a ValueError. Omitted start and end values refer to the sequence edges in the step direction.

  • s[3:3:-1] gives '' for 'network', and s[5:2:1] gives '' for 'computer'.
  • 'PYTHON'[:3] gives 'PYT', [1:4] gives 'YTH', [::2] gives 'PTO', and [::-1] gives 'NOHTYP'.
  • 'PYTHON'[-1:1:-2] gives 'NH', [0::-1] gives 'P', [0:0:-1] gives '', [-2:] gives 'ON', [:-2] gives 'PYTH', and [::-2] gives 'NHY'.
  • 'triangle'[6:1:-2] gives 'lni'.

A -1 in the start or stop is a position, while a -1 in the step indicates direction. s[::] makes a copy. Out-of-range slices are clipped, while out-of-range single indexes raise an error.

Built-in Functions for Strings

len(s) gives the number of characters, min(s) and max(s) give the lowest and highest code-point characters, sorted(s) returns a sorted list of characters, list(s) returns a list of characters, str(x) gives the string representation, ord(s) needs a single character, and chr(n) converts a code to a character. The in and not in operators check substrings, so 'th' in 'python' is True. Comparisons with <, >, ==, and != are lexicographic and case-sensitive.

Case Methods

Case methods return a new string and leave the original unchanged:

  • s.upper() converts all characters to uppercase.
  • s.lower() converts all characters to lowercase.
  • s.capitalize() uppercases the first character and lowercases the rest.
  • s.title() capitalizes each word.
  • s.swapcase() swaps upper and lower case.
  • s.casefold() performs aggressive lowercasing for comparisons.

Methods chain from left to right: 'hELLO wORLD'.lower().capitalize() gives 'Hello world', 'hELLO wORLD'.title() gives 'Hello World', and 'HELLO'.lower().upper() gives 'HELLO'. To keep a change, assign it: s=s.upper().

Classifiers

All classifiers return a boolean and are generally False for an empty string:

  • s.isalpha(): letters only.
  • s.isalnum(): letters and digits, no spaces.
  • s.isdigit(): digit characters.
  • s.isnumeric(): numeric symbols, including fractions.
  • s.isdecimal(): decimal digit characters, the most restrictive test.
  • s.isspace(): whitespace only, with at least one character.
  • s.isupper(): all cased letters are uppercase; digits are allowed, and at least one cased letter is required.
  • s.islower(): all cased letters are lowercase.
  • s.istitle(): words are in title case.

Examples: 'abc123'.isalnum() is True and .isalpha() is False; '123'.isdigit() is True; ' '.isspace() is True, but ''.isspace() is False; 'ABC123'.isupper() is True, but '123'.isupper() is False; 'Hello World'.istitle() is True, but 'hello world'.istitle() is False; '²'.isdigit() is True, '½'.isnumeric() is True, and '½'.isdigit() is False.

Search and Count

s.find(sub[,start[,end]]) returns the index of the first occurrence or -1 if it is missing. s.index(sub[,start[,end]]) returns the same index but raises a ValueError if missing. s.rfind(sub) finds the last occurrence, and s.count(sub[,start[,end]]) counts non-overlapping matches. All use 0-based indexes. 'banana'.find('na') gives 2, 'banana'.find('z') gives -1, 'banana'.count('a') gives 3, 'committee'.count('t') gives 2, and 'programming'.find('mm') gives 6. An index of 0 is a valid result, so do not confuse it with False.

Stripping, Splitting and Joining

s.strip() removes whitespace from both ends, s.lstrip() from the left only, and s.rstrip() from the right only. Internal characters are kept. s.strip(chars) removes any character in the given set from both edges, not a whole substring: 'xyHelloxy'.strip('xy') gives 'Hello', and 'good baby good'.strip('odog') gives ' baby '.

s.split(sep=None,maxsplit=-1) returns a list. With the default separator, whitespace groups are used: 'a b'.split() gives ['a','b']. With an explicit separator, empty pieces are kept: 'a b'.split(' ') gives ['a','','','b'], and 'a,b,,c'.split(',') gives ['a','b','','c']. 'a,b,c,d'.split(',',2) gives ['a','b','c,d']. The separator cannot be an empty string.

' '.join(['a','b']) gives 'a b', and all items must be strings. Note that 'a,b'.split(',') returns a list, not a tuple.

Replace and Start/End Checks

s.replace(old,new[,count]) returns a new string with all occurrences replaced unless a count is given: 'mississippi'.replace('s','z') gives 'mizzizzippi', and 'banana'.replace('a','o',1) gives 'bonana'. The replacement is case-sensitive.

s.startswith(prefix[,start[,end]]) and s.endswith(suffix[,start[,end]]) return booleans: 'Python'.startswith('Py') is True, but 'Python'.startswith('py') is False.

Escapes and Traversal

The escape \n is a newline, \t is a tab, \\ is a literal backslash, and \' is an escaped quote. Triple-quoted strings ('''...''' or """...""") allow multi-line text and docstrings. A \n counts as one character. print(repr(s)) helps reveal hidden whitespace and empty strings.

Iterate over characters with for ch in s:, or use indexes with for i in range(len(s)): and s[i]. To count matching characters, set count=0 and then use for ch in s: if ch.isdigit(): count+=1. A palindrome check is s==s[::-1], which is case-sensitive unless you normalize the string first. Note that min() and max() on a string compare characters, not word lengths.

Remember that s[2] returns one character, s.find('x') searches for the first occurrence, and s.count('x') counts occurrences. Methods such as upper, lower, title, capitalize, replace, and strip do not change s.

Common Output Traps

  • print(value[3:3:-1]) prints a blank line, since the result is the empty string '', not None.
  • print('python'[0].upper()) prints P, not PYTHON.
  • print('Apple aPPle'.lower().count('p')) prints 4.
  • print('python'[::-2]) prints nhy.
  • print('database'[:6:2]) prints dtb.

Functions, Modules, Lists, Tuples and Sets

Defining and Calling Functions

def name(param1,param2=default): defines a function with an indented body. Defining a function stores its code; the body runs only when the function is called with name(args). A parameter is a named placeholder in the definition, while an argument is the actual value passed in.

return expression sends a value back and exits the function. print(expression) only displays the value and returns None. A fruitful function returns a useful value, while a void-style function only performs actions or prints, which means it implicitly returns None.

  • def f(x): return x**3 followed by print(f(3)) prints 27.
  • def g(x): print(x**3) followed by print(g(3)) prints two lines: 27, then None.

A function with no explicit return, a bare return, or a path with no return gives None. A return statement prevents later statements in the body from running. Errors in uncalled functions or unexecuted branches do not occur, except syntax errors, which are detected when the code is parsed.

Function Arguments

Positional argument order matters, while keyword arguments such as f(b=3,a=2) bind by name. Defaults are used when an argument is omitted. Required ordinary parameters must come before parameters with defaults: def f(n,m=9,s=1): means f(4) sets n=4, m=9, s=1, and f(4,s=2) sets m=9, s=2. A signature such as def f(a=1,b): is invalid syntax. Missing, extra, or repeated arguments raise a TypeError.

Scope

A local variable inside a function shadows a global variable of the same name. The global x statement lets a function rebind the global x, and nonlocal x refers to the enclosing function’s x. Assigning to a local x makes it local throughout the function, so reading it before assignment raises an UnboundLocalError.

Other Function Features

def returns a function object. Writing f refers to the function, while f() executes it. help(f) and f.__doc__ show documentation, and the first statement in a function can be a docstring in triple quotes. Recursion means a function calls itself and needs a base case. A lambda x: x*2 creates a small function; sort(key=lambda item:item[1]) sorts by the second element of each tuple.

Built-in Functions

  • print, input, type, and isinstance(x,T).
  • id(x) gives an identity number, which is not proof of pooling.
  • int, float, str, bool, list, tuple, set, and dict are constructors.
  • len(x) gives the length, sum(numbers[,start]) gives the total, and min and max return extremes from a sequence or arguments.
  • abs(-3) gives 3, round(x,n) rounds, and pow(a,b) equals a**b.
  • sorted(iterable,key=...,reverse=False) returns a new list, and reversed(seq) returns a reverse iterator.
  • enumerate(seq) gives index and value pairs, and zip(a,b) gives pairs of items.
  • help(object) shows documentation, and dir(obj) lists available names.

For min and max with equal values, the first matching argument is kept: min(1,True) gives 1, and min(True,1) gives True. On a dictionary, min and max use the keys. sum([1,2]) gives 3, but sum(['a','b']) raises a TypeError.

The math and random Modules

import math provides math.sqrt(16) (4.0), math.exp(2) (e squared), math.log(x) (natural log), math.log10(x) (base-10 log), and math.pow(2,3) (8.0, a float). The ordinary 2**3 gives the integer 8. sqrt(-1) and log(0) raise a ValueError. With from math import sqrt, you can call sqrt(16) directly.

import random provides random.random(), a float from 0 up to but not including 1; random.randint(a,b), an integer that includes both endpoints; random.randrange([start,]stop[,step]), which excludes the stop; random.uniform(a,b), a random float; random.choice(seq), one element from a non-empty sequence; and random.shuffle(list), which shuffles in place and returns None. Results may differ on each run.

Lists

Lists are ordered, indexed, mutable, and allow duplicates. [] and list() create empty lists. list('Hi') gives ['H','i'], while ['Hi'] has one element and list(5) raises a TypeError. Indexing gives one element, and slicing gives a new list. Assigning lst[0]=99 changes the list, lst + other_list concatenates, and lst*3 repeats references, which can cause aliasing problems with nested lists.

The in and not in operators test membership, and len, min, max, sum (for numbers), and sorted all work on lists. After a=[1,2]; b=a, both names refer to the same list. Use b=a.copy() or b=a[:] to make a new outer list (a shallow copy). Copy and deepcopy differ for nested structures.

List Methods

  • a.append(x) adds one object at the end: [1,2].append([3,4]) gives [1,2,[3,4]].
  • a.extend(iterable) adds each item: [1,2].extend([3,4]) gives [1,2,3,4], and extend('34') adds '3' and '4'. extend(34) raises a TypeError.
  • a.insert(i,x) inserts before index i.
  • a.pop([i]) removes and returns the item at an index, by default the last one; an invalid index raises an IndexError.
  • a.remove(value) deletes the first matching value and returns None; a missing value raises a ValueError.
  • a.index(value[,start[,end]]) gives the first position, or raises a ValueError.
  • a.count(x) counts occurrences.
  • a.sort(key=...,reverse=False) sorts in place and returns None; sorted(a) returns a new sorted list.
  • a.reverse() reverses in place and returns None; a[::-1] returns a reversed copy.
  • a.copy() makes a shallow copy, and a.clear() empties the list.
  • del a[i], del a[i:j], and del a delete an item, a range, or the name itself.
  • a[i:j]=[] deletes a range, a[i:j]=[x,y] replaces a slice with two values, and a[i:j]=[[x,y]] replaces it with one nested list.

append, extend, insert, remove, sort, reverse, and clear return None, while pop returns the removed item. Note that print(a.sort()) prints None, not the list.

List Comprehensions and Loops

A list comprehension has the form [expression for x in iterable if condition]. For example, [n*n for n in range(5)] gives [0,1,4,9,16], and [n for n in range(6) if n%2==0] gives [0,2,4]. Use for x in lst: to iterate over values, or for i in range(len(lst)): to iterate over indexes. Avoid changing a list while iterating over it when possible.

Tuples

Tuples are ordered, immutable, and allow duplicates. () is an empty tuple, and (5,) is a one-element tuple, while (5) is just the integer 5. tuple([1,2]) converts a list to a tuple. You can read and slice tuples with t[0], t[-1], t[1:3], and t[::-1], but you cannot assign to items or append. Tuples support count, index, len, and min, max, sum for numeric tuples. Unpacking works as in a,b=(3,4). A tuple that contains a list can have that inner list modified.

Sets

Sets contain unique, unordered, mutable elements and do not support indexing. {1,2} creates a set, and {1,1,2} has two elements. Note that {} creates an empty dictionary, so use set() for an empty set. set('aba') gives the unique characters.

  • set.add(x) adds one item, and set.update(iterable) adds many.
  • set.remove(x) raises a KeyError if the item is missing, while set.discard(x) does nothing.
  • set.pop() removes an arbitrary element, set.clear() empties the set, and set.copy() makes a copy.
  • x in s tests membership.

Set operations include A|B (union), A&B (intersection), A-B (only in A), and A^B (in exactly one of the two). A<=B tests a subset, and A>=B tests a superset; the methods A.issubset(B) and A.issuperset(B) do the same. Set elements must be hashable, so a list cannot be a member. An ordinary set is mutable, while a frozenset is immutable.

Dictionaries, File I/O and Exam Traps

Dictionaries

A dictionary maps keys to values, for example d={'key':value,1:'one'} or dict(Course='ITSS3311'). {} and dict() create an empty dictionary. In modern Python, dictionaries keep insertion order and are mutable. Keys must be unique and hashable (strings, integers, or tuples without mutable parts), while values can be anything. A duplicate key keeps the last value: {1:3,1:5} becomes {1:5}.

  • d['key'] returns the value, but a missing key raises a KeyError.
  • d.get(key[,default]) returns the stored value or None (or the default) and does not insert a missing key.
  • d[key]=value adds or updates an entry, and d[key]+=1 increments a numeric value.
  • 'key' in d checks the keys, not the values; use 3 in d.values() to check values.
  • max(d), min(d), and sorted(d) work on the keys. Mixed unorderable key types cause a TypeError.

Other methods include d.keys(), d.values(), and d.items(), which return views (not lists); list(d.keys()) converts a view to a list. d.get(k,0) returns the value or 0. d.pop(k[,default]) removes the key and returns its value, and d.popitem() removes and returns the last inserted pair. d.update(other) adds or overwrites pairs and returns None. d.setdefault(k,default) returns the old value or inserts the default if the key is absent. d.clear() empties the dictionary, d.copy() makes a shallow copy, del d[k] removes an entry, and del d deletes the name. To rename a key, use d['new']=d.pop('old'). len(d) gives the number of pairs.

Loop over a dictionary with for key in d: or for key in d.keys(): for keys, for val in d.values(): for values, and for k,v in d.items(): to unpack pairs. For example, with d={'a':2,'b':3}, list(d.items()) gives [('a',2),('b',3)]. Use sorted(d) to alphabetize the keys.

Dictionary Get Cases

For d={'apple':2}: d.get('pear') gives None, d.get('apple') gives 2, d.get('pear',0) gives 0, and d.get('apple',0) gives 2. None of these change the dictionary. By contrast, d['pear'] raises a KeyError, and d['pear']=0 inserts the key.

Counting Pattern

To count characters with a dictionary, use counts={} and then for ch in 'banana': counts[ch]=counts.get(ch,0)+1, which gives {'b':1,'a':3,'n':2}. The same pattern works for words. To find the most frequent key, use max(counts,key=counts.get) on a non-empty dictionary. To check for presence, use if k in d:, or d.get(k,0) when a safe default is needed.

File I/O

open('file.txt','r') opens a file for reading; a missing file raises a FileNotFoundError. Mode 'w' writes and creates or truncates the file, 'a' appends to the end and creates the file if needed, and 'x' creates a new file and raises an error if it already exists.

  • f.read() reads all remaining content, and f.read(n) reads up to n characters.
  • f.readline() reads one line, and f.readlines() returns a list of the remaining lines.
  • for line in f: iterates over the lines.
  • f.write('text\n') writes a string with no automatic newline and returns the number of characters written.
  • f.close() closes the file, f.seek(0) returns to the beginning, and f.tell() reports the current position.

Using with open('file.txt','r') as f: closes the file automatically when the block ends. Use print(line,end='') to avoid doubled newlines. Reading starts at the current file pointer, so a repeated read can return an empty string. Mode 'w' erases existing content, while 'a' preserves it.

Common Exam Errors

  • SyntaxError: bad syntax, such as a missing colon, an invalid elif, or a required parameter after a default.
  • IndentationError: incorrect block spacing.
  • NameError: an undefined name.
  • UnboundLocalError: a local variable is read before assignment.
  • TypeError: a wrong type, such as '3'+3 or list(5).
  • ValueError: an invalid value, such as int('hi'), range(...,step=0), .index('missing'), or removing a missing item from a list.
  • IndexError: an index out of bounds, such as s[999] or list.pop(999).
  • KeyError: a missing dictionary key.
  • ZeroDivisionError: n/0 or n%0.
  • AttributeError: a missing method.
  • FileNotFoundError: reading a file that does not exist.
  • RecursionError: recursion that goes too deep.

Slices beyond bounds are clipped or return an empty result rather than raising an IndexError. A slice or range in the wrong direction gives an empty result, while a zero step raises a ValueError. After the first uncaught exception, the rest of the program does not run.

High-Yield Traces

  • 'network'[3:3:-1] gives ''; 'triangle'[6:1:-2] gives 'lni'; 'python'[::-2] gives 'nhy'; 'database'[:6:2] gives 'dtb'.
  • min('PYTHON') gives 'H'; min('cBaD') gives 'B'.
  • 'programming'.find('mm') gives 6; 'committee'.count('t') gives 2; 'mississippi'.replace('s','z') gives 'mizzizzippi'.
  • print(10/3) shows 3.333…, while format(10/3,'.2f') gives the string '3.33'. round(2.675,2) gives 2.67.
  • With def g(x): print(x*x) and print(g(3)), the output is two lines: 9, then None.
  • With def f(x): if x>5: return x-2 followed by x+3, print(f(4)) prints None, because an expression alone is not a return.
  • With a=2; b=a; b*=2, a is still 2 and b is 4.

Nested Conditions and Loops

If x=7 and y=3, then elif x%2==1 and y<x-4 checks 3<3, which is False, so the else branch runs. A chained comparison such as a>b>c+1 means both comparisons must hold. A nested break only exits the inner loop, pass is a no-op, and continue skips the rest of the iteration. In loops where total+=n runs before a break check, the total includes the value that triggered the break.

To trace code, update values line by line, apply precedence, identify the nearest block, record every print and return, and stop at a break, return, or error. For exact questions, decide whether the output is a number, a string, a list, an empty string, no output, None, or an error.

Number Bases and Classic Programs

The literals 0b1010 (binary), 0o12 (octal), and 0xA (hexadecimal) all equal decimal 10. bin(10) gives '0b1010', int('1010',2) gives 10, hex(26) gives '0x1a', and oct(8) gives '0o10'. Repeated n%2 gives the rightmost bit, and n//=2 shifts to the next bit. To convert without bin(), use if n==0: return '0', then result='' and while n>0: result=str(n%2)+result; n//=2, and return result.

A multiplication table uses for i in range(1,r+1): print(n,'x',i,'=',n*i). A leap-year test is year%400==0 or (year%4==0 and year%100!=0). A prime test checks that n>1 and that no divisor i exists in range(2,n). A factorial uses product=1; for i in range(1,n+1): product*=i, and Fibonacci numbers use a,b=b,a+b.