Chapter 2 — Python for Analysts: A Bear in the Archive I

Variables, values and types

16 min
O que você vai aprender
  • 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

A cadet examines a hologram where a tag moves between values and four capsule forms represent basic data types and conversion.
The = 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.

A variable is a name for a memory cellcodePython memoryorders = 1284avg_check = 730revenue = orders * avg_checkorders1284avg_check730revenue937320on line 3 Python substitutes the values: 1284 × 730name → value; “=” means “put it into the cell”
A variable is a label attached to a value in memory, not a box containing it. Assignment moves the label.

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:

TypeWhat it isExamples from the archive
intwhole number1284 orders, 730 roubles, -41 refunds
floatnumber with a fractional part6.0 percent conversion, 783.33 average check
strtext (a string)'Murmansk', '2025-03-14', '1240'
boollogical: 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 intint(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.

A live cell. First predict what each line will print, then run it and compare. Then change the values and run again.
python · pandas
Practice: write the code
A row of the March 14 daily export arrived entirely as text. Turn the three fields into numbers (orders, avg_check, refunds) and compute net_revenue — revenue after refunds: each refund takes away one average check.
python · pandas
Practice: write the code
The nightly DAU check. Monitoring sent two text values. Turn them into numbers, compute 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.
python · pandas
Check yourself
Two fields arrived from a CSV: a = '1240' and b = '380'. What does print(a + b) print?
Check yourself
An API returned an order amount as a string: raw = '1250.50'. What does int(raw) return?