2 Variables, Types, and Expressions
A practical introduction to Python names, assignment, built-in types, expressions, conversion, formatting, mutability, and clear coding choices.
Names and values
Python programs manipulate values. A value may be a number, text, collection, or another object. Names make values easier to use, while expressions combine values to produce new results.
A is a name whose associated value can change while a program runs. Python names should begin with a letter or underscore, continue with letters, digits, or underscores, and use consistent capitalization. Names are case-sensitive, so total, Total, and TOTAL refer to different names. Names also cannot be Python keywords such as if, class, or return.
Use descriptive snake_case names for ordinary variables. For example, customer_count communicates more clearly than n, and average_temperature communicates more clearly than x when the purpose of the value matters.
An is any piece of code that produces a value. Examples include a literal such as 42, a name such as user_name, a function call such as len("Python"), or a calculation such as subtotal * (1 + tax_rate).
Takeaway: Choose names that reveal purpose, and remember that expressions are evaluated to produce values.
Binding names with
associates a name with the result of an . Python evaluates the right-hand side first, then binds the resulting object to the name on the left. The symbol means “assign” in this context; it does not mean that two values are mathematically equal.
For example, a program can assign 8 to width, 5 to height, and then assign the result of width * height to area. A later can bind temperature to a different object, such as changing its associated value from 68 to 70.
Python supports multiple and unpacking. The names x and y can receive two values at once, and first and second can receive the elements of a sequence. Swapping two names can also be expressed as left, right = right, left, without a temporary .
binds a name to an object; it does not necessarily copy the object. If numbers refers to a list and other_numbers = numbers, both names refer to the same list. Appending an item through other_numbers therefore changes what is visible through numbers as well. To make a separate shallow list copy, use a slice such as numbers[:] or the list() constructor.
Do not confuse with comparison. Use to assign and == to compare values. Use is for identity checks, especially when checking whether a value is None.
Takeaway: changes name-to-object bindings, and assigning a mutable object does not automatically create a copy.
Types and Boolean logic
Every Python object has a type. The type() function reports the type of an object. Important built-in types include int for whole numbers, float for numbers with fractional parts, complex for complex-number calculations, bool for logical values, str for text, list for ordered changeable collections, tuple for ordered unchangeable collections, set for unique unordered values, dict for key–value mappings, and None for the absence of a value.
means that a name does not have a permanently declared type. For example, a name can first refer to the integer 10 and later refer to the string "ten". The object currently associated with the name determines the type at that moment.
does not make type compatibility irrelevant. Operations must still be valid for the objects involved. Adding the integer 5 to the string "5" raises a TypeError; converting the string with int("5") before addition produces a valid numeric operation.
A is either True or False. Comparisons such as age >= 18 produce Boolean values. Boolean operators combine conditions: and requires both conditions to support a true result, while or can succeed when at least one condition is true. Python uses short-circuit evaluation, so it may skip the right-hand operand when the result is already determined.
Python also tests objects for truth. Empty collections, 0, False, and None are false-valued; most other objects are true-valued.
Takeaway: The current object determines a name’s type, and valid operations still depend on the types of the objects involved.
Calculations and conversion
Arithmetic operators create numeric results. Addition, subtraction, multiplication, division, floor division, remainder, and exponentiation are represented by +, -, *, /, //, %, and **. For example, , , , and . In Python code, exponentiation is written with **, so the last operation is 2 ** 3.
Use parentheses when they make the intended order of operations easier to see. An average can be represented mathematically as
and written in Python as (quiz_1 + quiz_2 + quiz_3) / 3.
or casting creates a value of another type when the conversion is valid. int("42") produces an integer, float("19.95") produces a floating-point value, str(404) produces text, and bool(1) produces True. list("cat") produces a list of characters.
Conversions can fail. For example, int("four") raises a ValueError. Also, converting a floating-point value to an integer truncates toward zero rather than rounding: and .
The input() function always returns a string. Convert the result before performing numeric calculations, such as converting a quantity with int() and a unit price with float() before multiplying them.
Takeaway: Use operators deliberately, make precedence visible with parentheses, and convert input or other values explicitly when a different type is required.
Text, formatting, and
A string is a sequence of text characters. Strings can use single or double quotation marks. The + operator concatenates strings, while * repeats a string. For example, joining a first name, a space, and a last name creates one longer string, and repeating - can create a divider.
An makes interpolation readable. In an such as f"{name} was born in {year}.", the expressions inside braces are evaluated and inserted into the resulting string. Format specifications control presentation: .2f displays a floating-point value with two digits after the decimal point, while .1% displays a ratio as a percentage with one digit after the decimal point.
The str.format() method and the format() function are alternative formatting tools. Use str() when you need a human-readable string representation and repr() when a representation useful for debugging is more appropriate.
describes whether an object’s contents can change after creation. Lists, dictionaries, and sets are commonly mutable. Integers, floats, Booleans, strings, and tuples are commonly immutable.
A list can be changed in place by appending an item or replacing an element. A string cannot be changed in place; an operation such as converting "cat" to uppercase creates a new string, and the name can then be rebound to that new object. A tuple cannot have one of its own positions replaced, although a tuple may contain a reference to a mutable object such as a list, and that inner list can still change.
When two names share a mutable list or dictionary, a change made through one name may be visible through the other. Make a copy or create a new value when shared mutable state would be confusing.
Takeaway: Formatting controls how values are presented, while determines whether an existing object can change in place.
Writing clear Python expressions
Clear expressions are easier to test, explain, modify, and debug. Prefer descriptive names such as minutes_remaining over an unexplained m. Use parentheses when they improve comprehension, even when Python’s precedence rules would make them unnecessary.
Break complicated calculations into meaningful steps. Instead of hiding a complete calculation behind short names, compute a subtotal, then a discount, and finally a total. Intermediate names can document the algorithm and make each step easier to verify.
Keep related operations together and avoid repeating an whose meaning should remain stable. Compute it once and reuse the result. A short sequence of clear assignments is often better than one dense .
A useful review checklist is:
Does each name describe the value it refers to?
Are
=and==being used for their correct purposes?Are
ischecks reserved for identity, especiallyvalue is None?Are parentheses or intermediate names needed to make evaluation order clear?
Could a mutable object be shared unintentionally?
Are input values converted before numeric operations?
Would an make output easier to read?
The central relationship is simple: names refer to objects, binds names, types describe objects, expressions produce values, and determines whether those objects can change. Understanding these relationships makes Python code more predictable and readable.
Final takeaway: Write code so that both Python and another reader can follow the intended values, types, bindings, and changes.