Variables, values and types
What you'll learn
- create variables and understand what the
=sign actually does - tell the four basic types apart:
int,float,str,bool - ask a value for its type with
type()and convert between types:int(),float(),str() - understand why
'1240' + '380'gives'1240380'instead of 1620 — and why almost every analyst hits this on day one
A name, a label and a value
QUERY has unpacked the first crate of the black box — a daily export. The screen shows a column of numbers without a single caption.
"Numbers without names are noise. Give them names and they become testimony." — QUERY

= sign does not compare — it binds a name to a value, and the value's type decides what may be done with it at all.In the prologue you already wrote orders = 1284. Let us take that line seriously, because everything else stands on it.
orders = 1284
The = sign here is not mathematical equality. It is a command: "put the value on the right into the name on the left". Read it right to left: Python first evaluates the right-hand side, then binds a name to the result.
A handy picture: the value 1284 sits somewhere in memory and orders is a label stuck onto it. The label can be moved:
orders = 1284 # the label orders points at 1284
orders = 1310 # the same label moved to 1310; 1284 is no longer needed
print(orders) # 1310
Hence a line that looks odd but is completely ordinary:
orders = orders + 120 # take the current orders, add 120, call the result orders again
In maths x = x + 120 is nonsense. In Python it means "recompute and overwrite". The short form: orders += 120.
Naming rules. Latin letters, digits and _; may not start with a digit; case matters — orders and Orders are two different names. A name should explain what is inside: avg_check rather than x, dau_today rather than d1. In a week you will not remember what d1 was, but QUERY will remind you.
Common mistake #1. The sides are swapped:
1284 = orders # SyntaxError: cannot assign to literal
In the simple case shown here, the left of = is a name, the right is a value or an expression.
Common mistake #2. A typo or a different case:
orders = 1284
print(Orders) # NameError: name 'Orders' is not defined
NameError is the beginner's most frequent error, and it is almost always a typo, a capital letter, or a cell above that was never run.
The four types everything is made of
Every value in Python has a type — it decides what you may do with that value. Four of them are enough to start:
| Type | What it is | Examples from the archive |
|---|---|---|
int | whole number | 1284 orders, 730 roubles, -41 refunds |
float | number with a fractional part | 6.0 percent conversion, 783.33 average check |
str | text (a string) | 'Murmansk', '2025-03-14', '1240' |
bool | logical: only True or False | "is this day anomalous?" |
You can ask any value for its type with type():
type(1284) # <class 'int'>
type(783.33) # <class 'float'>
type('Murmansk') # <class 'str'>
type(True) # <class 'bool'>
Look at the third row of the table: '1240' is a string, even though there are digits inside the quotes. The quotes decide everything. 1240 is a number you can do arithmetic with; '1240' is text that merely looks like a number.
Arithmetic
1240 + 380 # 1620 addition
1240 - 380 # 860 subtraction
1284 * 730 # 937320 multiplication
1240 / 4 # 310.0 division — ALWAYS yields a float, even when it divides evenly
1240 // 400 # 3 floor division (how many times it fits)
1240 % 400 # 40 remainder
2 ** 10 # 1024 power
Remember the / line: 10 / 2 is 5.0, not 5. Python assumes division generally produces a fraction and does not pretend otherwise. When you need a whole number, wrap the result in int() or use //.
Comparisons produce bool
1240 > 1000 # True
730 == 640 # False == is the QUESTION 'are they equal?', = is the COMMAND 'assign'
730 != 640 # True not equal
6.0 >= 6.0 # True
'Murmansk' == 'murmansk' # False — case matters, string comparison is exact
The result of a comparison is an ordinary bool value, and you can store it in a variable:
is_big_day = orders > 1200
print(is_big_day) # True
These are your future filters: in chapter 3 pandas will select table rows with exactly these comparisons, only for every row at once.
Common mistake #3. Writing = where the question == belongs:
(orders = 1284) # SyntaxError
(orders == 1284) # this is correct
Why this is lesson one and not a footnote
Here is entry #3 from L.'s journal:
"Spent half a day working out why daily revenue came out as a 41-digit number. Answer: the export handed me the amounts as strings and I added them up. Python did not argue — it faithfully glued me half a kilometre of text."
That is not a curiosity, it is daily life. CSV files, some BI exports, and API responses may return values as strings. A CSV has no types at all: it is text separated by commas. And here is what happens if you fail to notice:
a = '1240' # came from a CSV — this is TEXT
b = '380' # so is this
a + b # '1240380' — not addition but gluing (concatenation)
For strings + means "stick one onto the other". No error is raised — and that is the dangerous part: the report will not crash, it will simply lie.
A mix of types, however, Python will not forgive:
'1240' + 380
# TypeError: can only concatenate str (not "int") to str
Translated from Pythonese: "you may glue only a string onto a string, and I was handed a number". The good news: this error is loud, you see it immediately.
Converting types
int('1240') # 1240 string → integer
float('730.5') # 730.5 string → float
str(1240) # '1240' number → string
int(730.9) # 730 float → int: the fraction is TRUNCATED, not rounded
round(730.9) # 731 this is rounding
int(' 1240 ') # 1240 int() forgives surrounding spaces
What int() does not forgive:
int('730.5') # ValueError: invalid literal for int() with base 10: '730.5'
int('1 240') # ValueError — a space inside
int('730 ₽') # ValueError — extra characters
The cure for the first case: float first, then int — int(float('730.5')) gives 730. The cure for the rest is cleaning the string, which is the next lesson's job.
One last trap
Strings compare like dictionary entries — character by character, not by magnitude:
'9' > '10' # True (!) because the character '9' comes after '1'
9 > 10 # False
If a sort "by amount" suddenly ranks 9 ₽ above 10,000 ₽, you are sorting strings, not numbers. It is a classic reporting bug and it takes two seconds to find: print(type(value)).
The investigator's rule: the first thing you do with new data is look at its types. Not "those look like numbers", but type() and your own eyes.
orders, avg_check, refunds) and compute net_revenue — revenue after refunds: each refund takes away one average check.drop_ratio — today's DAU as a share of yesterday's (plain division) — and raise the flag is_anomaly: True if today is below 80% of yesterday.a = '1240' and b = '380'. What does print(a + b) print?raw = '1250.50'. What does int(raw) return?