S
Saurav Danej
90-Day AI/ML LinkedIn Content System
← All days
3
Day 3 of 90Python

Python variables & types — the parts that matter

POST 1 of 5 MorningPythonConcept

Python isn't typeless — you just can't see them

Tell a Python beginner that Python has types and they'll usually look at you funny. 'Python is typeless, right? You just write x = 5 and it works.'

That's the most expensive misconception in the language. Python is dynamically typed, not typeless. There is a massive difference.

Every value in Python has a type. The integer 5 has type int. The string 'hello' has type str. What's flexible is the *variable*, not the value. The variable is just a label. You can re-point the label at a different value, and the value's type is whatever the new value's type is.

x = 10        # x points at an int
x = 'ten'     # now x points at a str
x = [1, 2]    # now x points at a list

The int 10 didn't 'change type' to a string. The variable just stopped pointing at 10 and started pointing at 'ten'. The values themselves are typed and immutable about it.

Why this matters in practice. When you see a function in someone else's code, you have no idea what type the variables are. Production bugs love this. You pass a string where the function expected a list, and the error doesn't surface for three function calls — buried under .append() failing on a string.

The fix isn't to abandon dynamic typing. It's to *annotate* what you mean — type hints (we cover them on Day 13). Hints don't change runtime behaviour. They give you, your IDE, and tools like mypy a way to catch the bugs before the code runs.

Dynamic typing isn't 'no types'. It's 'types you can't see unless you write them down'. Write them down.
#AI#MachineLearning#Python#100DaysOfCode#BuildInPublic#PythonTypes#Python3
POST 2 of 5 MiddayPythonDeep dive

The 7 built-in types you'll touch every day

Python has dozens of built-in types. Most of them you'll touch once a year. Seven you'll touch every single day. Get fluent in these and you can read 90% of Python code without a reference open.

int — arbitrary-precision whole numbers. Unlike C or Java, Python ints don't overflow. 2 ** 1000 is fine. Slower than fixed-width ints in C, but you almost never care.

float — IEEE-754 double precision. Same gotchas as every other language: 0.1 + 0.2 != 0.3 (it's 0.30000000000000004). For money, use the decimal module, not float.

str — immutable Unicode strings. 'café' has length 4, not 5, because Python counts Unicode code points, not bytes. Slicing returns a new string; concatenation creates a new string. We'll use this all the way through NLP week.

bool — True or False. Quirky fact: bool is a subclass of int. True == 1 and sum([True, True, False]) == 2. Use it; it's a built-in feature.

list — ordered, mutable, fast appends. Indexed by integer position. Searching by value is O(n) — if you find yourself searching a list a lot, you probably want a set or dict.

dict — hash map. Indexed by hashable keys. Insert, lookup, and delete are all O(1) average. As of Python 3.7, dicts preserve insertion order — that's now part of the language spec, not just CPython behaviour.

set — unordered collection of unique hashable items. Membership test is O(1). Useful for dedup, intersection, union, difference.

Know when each is the right choice and half of clean Python writes itself.
#AI#MachineLearning#Python#100DaysOfCode#BuildInPublic#DataStructures#PythonBasics
POST 3 of 5 AfternoonPythonCode

Mutable vs immutable — the bug everyone meets once

There's a Python bug so common, so subtle, and so universally caught at 2am that it deserves its own monument. The mutable default argument trap.

Look at the snippet. The author wanted a function that appends an item to a bucket, defaulting to a fresh empty list when no bucket is passed. Reasonable.

But Python evaluates default arguments *once*, at function definition time. Not once per call. So that empty list `[]` is created ONCE when the def statement runs. Every call without a bucket argument shares the same list.

First call adds 1. Second call adds 2 — but to the same list. The function silently accumulates state across calls. Now imagine this in a web server with concurrent requests. Or in a long-running ML pipeline. The bug shows up hours into a training run, after you've already shut your laptop and gone to bed.

The fix is one line. Default to None, then create a fresh list inside the function body when needed. Now each call starts clean.

Why does Python do this? Because evaluating default args once is faster, and because it lets you do clever caching tricks if you really want to. The cost is this footgun. The footgun is well-known. Linters (ruff, pylint) catch it. mypy doesn't, because the type is technically valid.

The broader lesson: mutable types in Python (list, dict, set) are passed by reference. If you mutate them inside a function, the caller sees the mutation. Immutable types (int, float, str, tuple) can't be mutated, so this whole class of bug doesn't happen for them.

Every Python developer meets this bug exactly once. Now you've met it.
#AI#MachineLearning#Python#100DaysOfCode#BuildInPublic#PythonGotchas#Debugging
POST 4 of 5 EveningPythonTip

f-strings beat every other formatting in Python

Three ways to format a string in Python. Only one of them is correct in 2026.

# old (don't)
'Hello %s, you are %d' % (name, age)

# legacy (also don't)
'Hello {}, you are {}'.format(name, age)

# correct (always this)
f'Hello {name}, you are {age}'

f-strings landed in Python 3.6 (year 2016) and have only gotten better since. They're faster than %-format and .format(). They're more readable. They support every format spec you'd want. And in 3.8 they gained a debugging trick that's worth its weight in gold:

f'{x=}' — produces 'x=42'. Print the variable name AND its value in one shot. Stop typing print(f'x = {x}'). Just print(f'{x=}'). Saves keystrokes; never gets the variable name out of sync with the label.

Format specs. f'{pi:.2f}' rounds to two decimals. f'{n:,}' adds thousand separators (1000000 → 1,000,000). f'{x:>10}' right-aligns to width 10. The full format spec mini-language is in the docs and worth a 10-minute read once.

Multi-line and nested f-strings work. Python 3.12 lifted the parsing limitations that used to make complex f-strings annoying. You can now nest quotes, embed expressions across lines, and use backslashes inside the braces.

If you see %-format or .format() in 2026 code, two possibilities. Either it's copied from a 2014 Stack Overflow answer the author didn't update, or it's running on Python 3.5 (please upgrade). Neither is a good reason to keep writing them today.

f-strings are not a stylistic preference. They're the answer.
#AI#MachineLearning#Python#100DaysOfCode#BuildInPublic#PythonTips#Python3
POST 5 of 5 NightPythonRecap

Day 3 — types are values, not labels

End of Day 3. Three days in, fifteen posts shipped. The pace is real and so is the ground we're covering.

What we did today.

Morning we got the foundational mental model right. Variables in Python are labels; types belong to the values they point at. This single sentence resolves probably 80% of the confusion beginners feel about why the language behaves the way it does.

Midday we listed the seven built-in types you'll touch every day — int, float, str, bool, list, dict, set. There are dozens more in the standard library, and you'll learn them as you need them, but those seven are the keyboard you play.

Afternoon we walked through the mutable default argument trap. It's the bug every Python developer meets exactly once, usually at 2am, usually in production. Now you've met it on Day 3 of week 1, and your future self will thank past-you for the inoculation.

Evening I made the case for f-strings being the only string formatting you should use in modern Python. f'{x=}' for debugging is worth the price of admission alone.

A quiet observation about pacing. Three days into a 90-day sprint, you've already touched: AI/ML framing, dev environment setup, and the type system foundations. That's three things most online courses cover in three weeks. Public learning is faster because there's nowhere to hide.

Tomorrow, Day 4, we go into the two collection types you'll never escape — list and dict. Slicing tricks, comprehensions, the dict-merge operator from Python 3.9. The day Python starts to feel ergonomic instead of just functional.

See you tomorrow.
#AI#MachineLearning#Python#100DaysOfCode#BuildInPublic#PythonJourney#DailyRecap