Skip to content

Programming Fundamentals & OOP

Variables and Data Types

A variable is a name a program uses to refer to a value stored somewhere in memory; assigning to it is how you give a value a name you can reuse. A data type is the category a value belongs to - integer, floating-point number, text, boolean, or a structured type like a list - and it determines which operations are legal and how the value is represented. Some languages require you to declare a variable's type up front and enforce it before the program runs (static typing); Python attaches the type to the value itself and lets a name refer to any type at any time (dynamic typing). Getting comfortable with both ideas is the first real skill in programming, because nearly every later concept assumes you already have it.

Why it matters

Every other concept in programming assumes you can name and hold a value
Functions take named parameters, loops track a counter, objects store attributes - all of it is variables underneath.
Type mismatches are one of the most common runtime failures
Adding a number to a piece of text, or comparing a string to an integer, is a beginner mistake that keeps happening at every experience level under time pressure.
The type you choose affects correctness, not just style
Storing money as a floating-point number instead of a fixed-precision type introduces rounding errors that a code review will not catch just by reading the logic.
Memory and performance depend on type
A language's fixed-width integer wraps around at a boundary a dynamically-sized one does not, and a large value copied by value costs more than one passed by reference.

What a variable actually is

Think of a variable as a label attached to a value, not a labeled box that holds the value itself. In Python, x = 5 does not create a box called x and put 5 inside it; it creates the value 5 somewhere, and makes the name x refer to it. Reassigning x to a new value just points the label somewhere else - it does not change the number 5. This distinction matters the moment two names can refer to the same value: if that value is mutable (like a list), changing it through one name is visible through the other name too, because there was only ever one value with two labels on it.

Python
x = 5
y = x
x = 10

print(x)  # 10
print(y)  # 5, unaffected - y still refers to the original 5

The core data types and how a language tells them apart

Most languages share a small set of built-in types: whole numbers (int), numbers with a fractional part (float), text (str), and true/false values (bool), plus structured types built from those, like lists and dictionaries. In a statically typed language, a variable's type is fixed when it is declared, and the compiler rejects code that violates it before the program ever runs. Python is dynamically typed: the type lives on the value, not the name, so the same name can refer to an integer on one line and a string on the next - the interpreter only checks that an operation is legal against a value's actual type when that line actually executes.

Python
value = 42
print(type(value))   # <class 'int'>

value = 'forty-two'
print(type(value))   # <class 'str'>

# This line only fails once it runs, not when the file is loaded:
# print(value + 1)   # TypeError: can only concatenate str to str

Mutable vs immutable, and the aliasing trap

Types split into mutable ones, whose contents can change after creation (lists, dictionaries, sets), and immutable ones, which cannot (numbers, strings, tuples). Reassigning an immutable value's name always creates a new value; changing a mutable value's contents changes the one value every name pointing at it sees. This is why two names that refer to the same list can surprise you: appending through one name is visible through the other, because there was only ever one list, not a copy. Immutability also explains why strings and tuples are safe to use as dictionary keys and mutable lists are not - a key's identity has to stay stable for a lookup to keep working.

Mistakes people make here

Assuming two variables pointing at the same list are independent copies
Assignment does not copy a mutable value; it copies the reference to it. b = a makes b point at the exact same list as a, so mutating one through a method like append changes what the other sees too. A real copy needs an explicit copy() or list().
Comparing floating-point numbers for exact equality
Most decimal fractions cannot be represented exactly in binary floating point, so 0.1 + 0.2 == 0.3 is false in nearly every mainstream language, Python included. Compare with a small tolerance instead, or use a fixed-precision type for money.
Expecting an integer to silently wrap around or overflow
In languages with fixed-width integers, such as a 32-bit int in Java or C, a value that exceeds the limit wraps or errors. Python's integers grow automatically to fit the value, so defensive code carried over from those languages is solving a problem Python does not have.
Concatenating values of different types without converting them first
Python will not silently turn a number into text the way some scripting languages do. Adding a text label directly to a number raises a TypeError; the number has to be converted explicitly with str(), or built into an f-string instead.

Strengths and trade-offs

Where it is strong

  • A named variable makes intent legible - the next reader does not have to guess what a bare 42 or a bare string constant means in context.
  • Types encode guarantees for free: once you know a value is a list, you know it supports indexing and appending without re-checking.
  • Dynamic typing, as in Python, removes a layer of upfront ceremony, so a first program can be three lines long with no type declarations at all.

The trade-offs

  • Dynamic typing trades early error-catching for flexibility - a type mistake surfaces only when that exact line runs, sometimes long after the code was written.
  • Static typing catches more mistakes before the program ever runs, but costs more upfront syntax and discipline to satisfy the compiler.
  • Implicit conversion rules differ enough between languages that intuition from one actively misleads in another.

Who needs this

Every programmer, on day one, in every language. It is also worth re-learning per language: the rules around typing, conversion, and mutability differ enough between Python, JavaScript, Java, and C that assuming they all work like the first language you learned is a common source of bugs when switching.

Questions about variables and data types

What is the actual difference between a variable and the value it holds?
The variable is a name; the value is the actual data sitting in memory. Assignment binds the name to the value - it does not copy the value into the name. This is why two names can end up referring to the exact same mutable value.
Why does Python let me store anything in a variable without declaring its type?
Because Python is dynamically typed: the type is a property of the value, not the name. The interpreter checks whether an operation is valid for a value's type only when that operation actually runs, not ahead of time.
Is a string a data type or a collection?
Both, in a sense - a string is its own built-in type, but it also behaves like an ordered sequence of characters: you can index into it, slice it, and loop over it the same way you would a list, just without being able to change it in place.
Why don't 0.1 + 0.2 and 0.3 come out equal?
Floating-point numbers are stored in binary, and most decimal fractions, including 0.1 and 0.2, have no exact binary representation, so they are stored as the closest approximation. Adding two approximations does not always land exactly on the approximation of the expected result. This is a property of the floating-point format, not a bug in any particular language.

The primary source

Related concepts

← All concept guides