Python tutorials  /  Python Variables and Data Types
Chapter 3 · Python

Python Variables and Data Types

A variable in Python is a named reference to a value stored in memory, created simply by assigning a value to a name using the '=' operator, without requiring an explicit type declaration beforehand. A data type specifies the kind of value a variable holds, such as numbers, text, or boolean values, and Python is dynamically typed, meaning a variable's type is determined automatically at runtime based on the value assigned to it, and can even change if reassigned to a different type of value later.

Think of a Python variable like a sticky note label you can place on any box, without needing to decide in advance what kind of box it will be. You can put a label called 'age' on a box holding the number 25, and later, without any special permission, move that same label onto a completely different box holding the text 'twenty-five' instead — Python doesn't lock you into one specific box type like some other languages do. This flexibility is called dynamic typing, and it's one of the biggest differences beginners notice when coming from a statically-typed language like Java.

Consider a simple inventory tracking script for a small online store. A variable 'product_name' holds text (a string) like 'Wireless Mouse', 'price' holds a decimal number (a float) like 19.99, 'quantity_in_stock' holds a whole number (an int) like 150, and 'is_available' holds a boolean (True/False) indicating whether the product can currently be ordered. Because Python doesn't require explicit type declarations, a developer can quickly write and test this kind of script without the extra boilerplate of specifying types everywhere, which is a major reason Python is favored for rapid prototyping and small-to-medium automation scripts in real businesses.

Data types are fundamental because they determine what operations are valid on a given piece of data (you can't meaningfully divide a person's name by a number) and how much memory is needed to store it. Python's dynamic typing removes the need for verbose upfront type declarations, making code faster to write and more flexible, especially for beginners and rapid prototyping. However, understanding the underlying data types remains essential, since operations that mix incompatible types (like adding a number directly to text) will still raise runtime errors, and knowing exactly what type a variable currently holds is critical for writing correct, bug-free code.

  • Numeric Types (int, float, complex): 'int' represents whole numbers of arbitrary size (Python automatically handles very large integers without overflow), 'float' represents decimal/floating-point numbers, and 'complex' represents complex numbers with a real and imaginary part (rarely used outside specialized scientific computing).
  • Text Type (str): Represents a sequence of Unicode characters (text), created using either single quotes ('text') or double quotes ("text"), with no distinct 'char' type for single characters like in Java — a single character is just a string of length 1.
  • Boolean Type (bool): Represents one of exactly two values, 'True' or 'False' (capitalized, unlike Java's lowercase 'true'/'false'), commonly used for conditional logic and flags.
  • Collection Types (list, tuple, dict, set): 'list' is an ordered, mutable (changeable) collection of items; 'tuple' is an ordered, immutable (unchangeable) collection; 'dict' stores key-value pairs; 'set' stores unique, unordered elements — all fundamental built-in data structures used constantly in real Python code.
variable_name = value # Examples: age = 25 price = 99.99 name = "CompileX" is_active = True fruits = ["apple", "banana", "cherry"]
A beginner needs to store different kinds of information about a student — their roll number, height, name, and whether they passed an exam — and wants to understand which Python data type is appropriate for each, along with how Python's dynamic typing lets a variable's type change after reassignment.
Declaring Variables and Checking Their Types
This example creates variables of different data types to store a student's details, then uses the built-in 'type()' function to inspect each variable's actual data type at runtime.
Python
roll_number = 101 height = 5.8 name = "Aditi" has_passed = True print("Roll Number:", roll_number, "| Type:", type(roll_number)) print("Height:", height, "| Type:", type(height)) print("Name:", name, "| Type:", type(name)) print("Passed:", has_passed, "| Type:", type(has_passed))
Roll Number: 101 | Type: <class 'int'> Height: 5.8 | Type: <class 'float'> Name: Aditi | Type: <class 'str'> Passed: True | Type: <class 'bool'>
Unlike Java, no explicit type keyword (like 'int' or 'String') is written before the variable name — Python automatically infers each variable's type based purely on the value assigned to it. The built-in 'type()' function returns the actual class/type of any value, which is extremely useful for debugging and confirming what kind of data a variable currently holds at any point in the program.
Dynamic Typing: A Variable Can Change Type When Reassigned
This example demonstrates Python's dynamic typing by reassigning the same variable name to values of completely different types, showing that Python allows this without any error, unlike statically-typed languages.
Python
value = 42 print("Value:", value, "| Type:", type(value)) value = "now I'm a string" print("Value:", value, "| Type:", type(value)) value = 3.14 print("Value:", value, "| Type:", type(value))
Value: 42 | Type: <class 'int'> Value: now I'm a string | Type: <class 'str'> Value: 3.14 | Type: <class 'float'>
The exact same variable name 'value' is reassigned three separate times to completely different data types (int, then str, then float), and Python allows every single one of these reassignments without any compile-time or runtime error, since it doesn't lock a variable to a fixed type upon its first assignment — this flexible behavior is the essence of Python's dynamic typing, quite different from Java's strict static typing, where a variable's declared type can never change.
  • Mixing Incompatible Types in Operations (TypeError): Attempting to directly concatenate a string with a number, such as 'print("Age: " + 25)', raises a 'TypeError: can only concatenate str (not "int") to str', since Python does not automatically convert numbers to strings during the '+' operation (unlike Java). The number must be explicitly converted first using 'str(25)'.
  • Confusing Mutable and Immutable Collection Types: Beginners often try to modify a 'tuple' directly (e.g., 'my_tuple[0] = 10'), not realizing tuples are immutable and this raises a 'TypeError: 'tuple' object does not support item assignment'. If a collection needs to be changed after creation, a 'list' should be used instead of a 'tuple'.
  • Using Uppercase 'True'/'False' Incorrectly or Lowercase by Mistake: Writing 'true' or 'false' in lowercase (following habits from Java or JavaScript) instead of Python's required capitalized 'True' and 'False' results in a 'NameError: name 'true' is not defined', since Python treats lowercase 'true' as an undefined variable name rather than the boolean literal.
  • Assuming Integer Division Behaves the Same as Java's: Writing '7 / 2' in Python 3 returns '3.5' (a float) by default, since the single forward slash always performs true/float division, unlike Java where dividing two ints truncates to '3'. Beginners expecting Java-like integer division behavior must explicitly use the double-slash floor division operator, '7 // 2', to get the truncated integer result of '3'.
  • Use snake_case for Variable Names: Follow Python's PEP 8 convention of using all-lowercase words separated by underscores for variable names (e.g., 'total_price', 'is_eligible'), rather than Java-style camelCase, to stay consistent with the vast majority of existing Python code and community expectations.
  • Use type() or isinstance() to Verify Types When Debugging: When unsure of a variable's current type (especially in dynamically-typed code where a variable's type could change), use 'type(variable)' for a quick check, or 'isinstance(variable, expected_type)' for a more robust type-checking condition within actual program logic.
  • Prefer Lists Over Tuples When Data Needs to Change: Choose a 'tuple' when a fixed, unchanging collection of values is intentional (like geographic coordinates or RGB color values), signaling to other developers that this data should never be modified; choose a 'list' whenever the collection genuinely needs to grow, shrink, or have its elements changed during the program's execution.
  • Use Explicit Type Conversion Functions When Combining Types: Always explicitly convert values to a compatible type before combining them in operations that don't support automatic conversion, such as using 'str(number)' when concatenating a number into a string with '+', or 'int(text_input)' when converting user-provided text input into a usable number for calculations.
What does it mean that Python is a 'dynamically typed' language, and how does this differ from a statically typed language like Java?
In a dynamically typed language like Python, a variable's type is determined automatically at runtime based on the value currently assigned to it, and a single variable name can be reassigned to hold values of entirely different types throughout a program's execution, with no compile-time type declaration or checking required at all. In a statically typed language like Java, a variable's type must be explicitly declared upfront (e.g., 'int age;'), and the compiler strictly enforces that this variable can only ever hold values of that declared type for its entire lifetime, catching type-mismatch errors at compile time before the program even runs. Python's approach offers more flexibility and faster development for many use cases, while Java's approach can catch certain classes of bugs earlier, before runtime.
What is the key difference between a Python list and a Python tuple, and when would you choose one over the other?
A 'list' is a mutable, ordered collection, meaning its elements can be added, removed, or changed after the list is created (using methods like 'append()' or direct index assignment). A 'tuple' is an immutable, ordered collection — once created, its elements cannot be changed, added, or removed at all; attempting to do so raises a 'TypeError'. Choose a list when the collection genuinely needs to be modified over the program's lifetime (like a dynamically growing shopping cart), and choose a tuple when the collection represents a fixed, unchanging group of related values (like a coordinate pair or a database record's fields), which also offers a slight performance benefit and communicates clear intent to other developers reading the code that this data is not meant to be altered.
Why does '7 / 2' return 3.5 in Python 3, and how would you get the integer result of 3 instead?
In Python 3, the single forward-slash division operator ('/') always performs TRUE DIVISION, returning a float result regardless of whether the operands are integers, specifically to avoid the sometimes-confusing implicit truncation behavior that integer division has in many other languages (including Python 2, where '/' between two ints used to truncate). To get the truncated, integer-style division result (discarding any remainder) in Python 3, the double-forward-slash FLOOR DIVISION operator ('//') must be used instead, so '7 // 2' correctly returns '3'. Note that floor division rounds DOWN toward negative infinity, not simply truncating toward zero, which matters for negative number results (e.g., '-7 // 2' returns '-4', not '-3').
Declare four variables to store the following details about a movie: its title (text), rating out of 10 (decimal number), release year (whole number), and whether it's currently available for streaming (True/False). Print all four values along with their types.
title = "Inception" rating = 8.8 release_year = 2010 is_streaming = True print("Title:", title, type(title)) print("Rating:", rating, type(rating)) print("Release Year:", release_year, type(release_year)) print("Is Streaming:", is_streaming, type(is_streaming))
What will be the output of the following code, and why? x = 10 print(type(x)) x = "ten" print(type(x)) result = 7 // 2 print(result)
The output will be: <class 'int'> <class 'str'> 3 The variable 'x' is first assigned an integer (10), so 'type(x)' shows 'int'. It is then reassigned to a string ("ten"), and since Python is dynamically typed, this reassignment is allowed without error, and 'type(x)' now correctly shows 'str'. Finally, '7 // 2' uses the floor division operator, which performs integer-style division and discards the remainder, correctly returning '3' rather than the float '3.5' that a single slash '/' would have produced.
Write a Python program that attempts to concatenate a string with a number directly using '+', observe the resulting error, and then fix it using proper type conversion.
age = 25 # This line would raise a TypeError if uncommented: # print("I am " + age + " years old") # Corrected version using explicit type conversion: print("I am " + str(age) + " years old") # Output: # I am 25 years old # The original code fails because Python does not automatically convert an int to a str during '+' concatenation with a string, unlike Java. Wrapping 'age' in 'str()' explicitly converts it to a string first, allowing the concatenation to succeed.

Python variables are created through simple assignment without explicit type declarations, reflecting Python's dynamically-typed nature where a variable's type is determined by its current value and can change upon reassignment. Core data types include numeric types (int, float), text (str), boolean (bool), and built-in collections (list, tuple, dict, set), each suited to different needs around mutability and structure. Understanding dynamic typing, the distinction between mutable and immutable collections, and Python 3's true division versus floor division behavior are essential foundational concepts before progressing to operators and control flow.

© 2026 CompileX. Maintained by Aditya Kumar Sharma.