Most code in an e-commerce app deals with numbers: prices, quantities, stock counts, ratings, totals. Python gives you three built-in numeric types for the job, and picking the right one matters more than it looks. This lesson covers what int, float, and complex are, how to write number literals in a readable way, and when each type is the right tool.
Python has three numeric types out of the box:
| Type | What it stores | Example | Typical use |
|---|---|---|---|
int | Whole numbers, positive or negative | 42, -7, 0 | Counts, quantities, stock levels |
float | Decimal numbers (real numbers) | 19.99, 3.14, -0.5 | Prices, ratings, percentages |
complex | Numbers with a real and imaginary part | 2+3j, 1j | Scientific and signal processing work |
You can check the type of any value with the built-in type() function:
type() returns the class of the value. The output <class 'int'> is Python's way of saying "this value is an int". You don't declare types when you assign a variable: Python figures it out from the value on the right of the =.
Here's how the three types fit together visually:
For day-to-day code you'll mostly use int and float. complex shows up only in math-heavy domains. This lesson covers all three so you recognize them when you see them.
int)An int is a whole number. Counts, quantities, stock levels, order IDs, and discount percentages (as whole numbers) all fit naturally here.
One thing that surprises people coming from other languages: Python integers have no fixed size. In many languages an int is 32 or 64 bits, and once you cross that limit you get overflow. Python's int grows as large as you need, limited only by available memory.
The number 10 ** 50 is a 1 followed by 50 zeros. It's still an int, and Python handles it without complaint. This is called **arbitrary precision**: the type can represent integers of any size. You won't run into overflow when totaling a cart, counting orders, or computing factorials.
Cost: Arbitrary precision isn't free. Operations on huge integers are slower than on small ones because Python has to work with the digits as a multi-piece value. For everyday e-commerce numbers (cart counts, stock, IDs) the difference is invisible. For million-digit math, it adds up.
Most of the time you write integers in decimal (base 10), the way you'd write them on paper:
Python also lets you write integers in three other bases by using a prefix:
| Base | Prefix | Example | Decimal value |
|---|---|---|---|
| Binary (base 2) | 0b | 0b1010 | 10 |
| Octal (base 8) | 0o | 0o17 | 15 |
| Hexadecimal (base 16) | 0x | 0xff | 255 |
These prefixes only change how you write the literal. Once Python stores the value, it's a normal int. The variable doesn't remember whether you typed 0b1010 or 10. You'll see hexadecimal a lot when working with colors, file permissions, or low-level byte data. Binary and octal are rarer in application code.
Large integers are hard to read. Is 10000000 ten million or one hundred million? Python lets you add underscores anywhere inside a numeric literal to group digits. Python ignores them, but your eyes don't:
The underscores don't appear in the output, they're purely a writing aid. You can use them anywhere except at the start or end of a number, and not two in a row. They work with floats and other bases too:
Use this in any code where a number is bigger than four or five digits. Reviewers will thank you.
float)A float represents a decimal number. Prices, ratings, weights, percentages with fractions, and anything else with a fractional part is a float.
Any number written with a decimal point is a float, even if the decimal part is zero:
5 is an int, 5.0 is a float. They look almost the same but have different types.
For very large or very small numbers, you can use scientific notation with e or E. The number before e is the mantissa, the number after is the exponent (power of 10):
Notice that any literal written with e is a float, even if it represents a whole number like 1e3 (which is 1000.0, not 1000). Python switches between regular and scientific notation when printing based on the size of the number, but the underlying value is the same.
Here's the trap that catches every Python beginner sooner or later. Type this into the REPL:
That's not a typo. The sum of 0.1 and 0.2 in Python is not exactly 0.3. It's 0.30000000000000004, a tiny bit larger. This isn't a Python bug. It's how almost every modern language stores decimal numbers.
The reason is that float follows a standard called IEEE 754 that represents numbers in binary, not decimal. Some decimals that look simple in base 10 (like 0.1) can't be written exactly in binary. They turn into repeating binary fractions that get rounded to fit in 64 bits. The rounding error is tiny, but it shows up when you do arithmetic:
total == 0.3 is False because total isn't exactly 0.3. This trips people up when checking sums against expected values. The fix in most everyday code is to compare with rounding or a small tolerance:
For now, just remember:
float is fast and good enough for most prices, ratings, and percentages.== to compare two floats you've computed.decimal. For learning and most everyday math, float is fine.Cost: Float arithmetic is fast (the CPU handles it directly), but the rounding errors accumulate when you do many operations in a row. Summing 1,000 prices with float gives a result that's usually correct to about 15 significant digits, which is plenty for cart totals but not for bank-grade accounting.
complex)A complex number has two parts: a real part and an imaginary part. You write the imaginary part by suffixing a number with j (Python uses j, not i, following the engineering convention):
You won't use complex for products, prices, or carts. It shows up in signal processing, electrical engineering, physics, and some graphics code. We're covering it here so you know it exists and recognize it if a library returns one.
You can pull the two parts out with the .real and .imag attributes:
Notice that both .real and .imag come back as float values, not int. That's true even when you wrote whole numbers in the literal. Complex numbers in Python always store their two parts as floats.
Arithmetic with complex numbers works the way it does in math:
You can mostly forget complex exists until you find yourself reading a tutorial that uses it. The takeaway: j after a number means it's the imaginary part of a complex number, and .real and .imag access the two halves.
Most of the time the decision is obvious from what you're modeling. A few quick rules:
| Situation | Use |
|---|---|
| Counting things (items in cart, stock, page number) | int |
| Discrete IDs (order ID, customer ID) | int |
| Money for learning and small projects | float |
| Money for real billing or accounting | decimal |
| Ratings, percentages, weights, anything with a fraction | float |
| Scientific work with imaginary components | complex |
A quick decision tree:
A common mistake is reaching for float when int would do. If you're counting items in a cart, cart_count = 3 is right, not cart_count = 3.0. The wrong type doesn't cause errors, but it makes intent fuzzy and can creep into bugs later when code expects a whole number.
Another mistake is the opposite: using int for money because "I want it exact" and then dividing it by 100 at the end. That works for simple cases, but you've now made every arithmetic operation a place to remember the decimal point yourself. For learning exercises, float is the path of least resistance.
Putting it all together with one short script:
A couple of things worth noticing in the output. The order ID 10_245 prints as 10245 because the underscore is only in the source code, not the value. The discount 0.10 prints as 0.1 because trailing zeros after the decimal are dropped on display. And type(x).__name__ gives the short name ('int') instead of the full <class 'int'> form, which is handy when you want a clean message.
These are the three numeric types you'll deal with in Python. Everything else, from bool to decimal and fractions, is built on top of these or sits beside them.
10 quizzes