Skip to content
VLSI Mentor

Python Part I · Module 2 · Variables and Data Types

Dynamic Typing: Names Do Not Have Types

You have now met two facts separately and this chapter puts them together. A name refers to a value, and a type belongs to a value. Follow that through and something falls out: nothing stops a name being pointed at a number on one line and a piece of text on the next, because the name was never the thing carrying the type. Python allows exactly that, and the property has a name — dynamic typing. It is often described carelessly, including by people who use it daily, so the chapter is precise about what it does and does not mean. It then spends its second half on the part that matters in practice, which is that being allowed to do something is not the same as it being a good idea in a script somebody else has to maintain.

Foundation9 min readPythonPart IFundamentalsTypesDiscipline

Part I · Module 2 · Chapter 2.12 · Dynamic Typing: Names Do Not Have Types

1. Two Facts You Already Have

From Chapter 2.2: a name refers to a value, and assignment can point it somewhere else.

From Chapter 2.10: a type belongs to a value — type(4210) asked the value what it was.

Put those together and a consequence appears that nobody has yet stated.

2. The Consequence

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
count = 5
print(type(count))

count = "five"
print(type(count))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
<class 'int'>
<class 'str'>

The same name reported two different types, because it was pointed at two different values. Python did not complain, warn, or require anything to be declared.

This property is called dynamic typing.

Two stages. After the first assignment the name count refers to the value 5, whose type is int. After the second assignment count refers to the value five as text, whose type is str. The name is unchanged in both; only what it refers to differs.countafter line 15type intcountafter line 3"five"type str12
Figure 1 — the type travelled with the value, not with the name. Reassignment pointed the name at a different value, and that value brought its own type. Nothing about the name changed, because the name never carried a type to begin with.

3. Saying It Accurately

Dynamic typing is regularly described in a way that is wrong, so here is the careful version.

Wrong: "Python variables have no type."

Wrong: "Python doesn't have types."

Right: "Values have types. Names do not. A name can be reassigned to a value of any type."

Python's types are real and they are enforced. Chapter 2.11 showed int("n/a") raising an error rather than guessing, and Chapter 2.9 showed text refusing to behave as a number. Python is strict about what you may do with a value.

What it does not do is require you to declare, in advance, which types a name will ever refer to.

4. Why This Is Convenient

The obvious benefit: less ceremony. You write seed = 4210 rather than declaring a type first, and short scripts get written faster.

The more interesting benefit shows up in conversion:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
seed_text = "4210"
seed = int(seed_text)

Two names, two types, no declarations, no casting syntax. Chapter 2.11's conversions read naturally precisely because names are not committed to a type.

5. Why It Needs Discipline

Now the half that matters for anything you will maintain.

Python permits this:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
result = 5
result = "five"
result = None
result = 500.0

Every line is legal. And a reader arriving at line 40 of that file has no way to know what result refers to without tracing every assignment above it.

There is an important distinction here, though, and it is worth being precise about.

Reasonable — the name keeps one meaning, and the type change is a deliberate, one-way conversion:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
seed_text = "4210"
seed = int(seed_text)

Two names. Each keeps its meaning. The type difference is the whole point.

Unreasonable — one name, two meanings:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
seed = "4210"
seed = int(seed)

This works, and it is the version you will see in real code. It reuses one name for the text form and the number form, which means the type of seed depends on which line you are looking at. In three lines that is survivable. In a fifty-line function it is how people lose an afternoon.

6. The Habit

Let a name mean one thing for its whole life.

If a value needs converting, give the result its own name — seed_text and seed, runtime_text and runtime_s. It costs one extra name and it means a reader can trust what they see.

This is the same argument as Chapter 2.4's naming discipline, one level up: there, a good name told the reader what the value is; here, a stable name lets them believe it.

7. What Is Deferred

Python does have a way to write down what type a name is expected to refer to. It is optional, it is not enforced when the program runs, and it is genuinely useful in larger scripts.

It is Module 11 — Functions, because it is most valuable at the boundaries where one piece of code hands a value to another. Introducing it here, before there are any such boundaries, would be notation without a purpose.

8. Predict, Run, Observe

Predict every line, including types.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
value = 10
print(value)
print(type(value))

value = "ten"
print(value)
print(type(value))

value = None
print(type(value))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
10
<class 'int'>
ten
<class 'str'>
<class 'NoneType'>

Then answer for yourself: at the last line, could a reader who joined at that point tell what value had been earlier? That question is the whole argument of §5.

9. Exercise

Exercise 1 — demonstrate it. Write a file where one name refers in turn to a whole number, a decimal, some text, and None, printing the type each time. Confirm Python never objects.

Exercise 2 — say it correctly. A colleague says "Python variables don't have types". Correct them in one sentence without saying they are entirely wrong — because the thing they are pointing at is real.

Exercise 3 — judge two versions. Which of these would you accept in review, and why?

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
# version A
seed_text = "4210"
seed = int(seed_text)

# version B
seed = "4210"
seed = int(seed)

Both work. Give the reason in terms of what a reader of line 40 can rely on.

Exercise 4 — the maintenance question. A script has a name result that refers to text in one place, a number in another and None in a third. You have been asked to add a feature. Name two specific things you now have to do before you can safely write a single line.

10. Summary

  • Values have types; names do not. A name is a label, and it can be pointed at a value of any type.
  • This property is called dynamic typing — and "Python has no types" is the wrong way to describe it. Python's types are real and enforced when values are used.
  • The difference from C or SystemVerilog is the absence of a declaration, not the absence of type checking.
  • It makes conversion read naturally, which is why Chapter 2.11 needed no casting syntax.
  • Permitted is not desirable. A name that changes meaning partway through costs every future reader a trace through the file.
  • Give a converted value its own name — seed_text and seed. One extra name; a reader who can trust what they see.
  • Optional type annotations exist and are deferred to Module 11, where there are boundaries worth annotating.

Two chapters left. The next one takes the name/value model one step further and asks a question that has been lurking since Chapter 2.3: can a value itself ever be changed?

Where this fits

Part of the Python curriculum.