Strong vs weak, dynamic vs static

Published

2023-07-31

Dynamic typing

You may have heard of “strongly typed” languages or “weakly typed” languages. These terms do not have precise definitions, and they are of limited utility. However, it’s not uncommon to hear people referring to Python as a weakly typed language. This is not the case. If we’re going to use these terms at all, Python exists toward the strong end of the spectrum. Python prevents most type errors at runtime, and performs very few implicit conversions between types—hence, it’s more accurately characterized as being strongly typed.

Static and dynamic typing

Much more useful—and precise—are the concepts of static typing and dynamic typing. Some languages are statically typed, meaning that types are known at compile time—and types of objects (variables) cannot be changed at runtime—the time when the program is run.

Python, however, is dynamically typed. This means that the types of variables can change at runtime. For example, this works just fine in Python:

>>> x = 1
>>> print(type(x))
<class 'int'>
>>> x = 'Hey! Now I am a string!'
>>> print(type(x))
<class 'str'>

This demonstrates dynamic typing. When we first create the variable x, we assign to it the literal value 1. Python understands that 1 is an integer, and so the result is an object of type 'int' (which is short for “integer”). On the next line, we print the type of x, and Python prints: <class 'int'> as we’d expect. Then, we assign a new value to x, and Python doesn’t miss a beat. Since Python is dynamically typed, we can change a variable’s type at runtime. When we assign to x the value 'Hey! Now I am a string!', the type of x becomes 'str' (which is short for “string”).

In statically typed languages (say, C or Java or Rust) if we were to attempt something similar, we’d receive an error at compile time.

For example, in Java:

int x = 1;
x = "Hey! Now I am a string!";

would result in a compile-time error: “incompatible types: java.lang.String cannot be converted to int”.

Notice that, unlike Python, when declaring a variable in Java a type annotation must be supplied, and once something is declared as a given type, that type cannot be changed.

It’s important to note that it’s not the type annotation

int x = 1

that makes Java statically typed. For example, other languages have type inference but are still statically typed (Python has limited type inference). Type inference is when the compiler or interpreter can infer something’s type without having to be told explicitly “this is a string” or “this is an integer.” For example, in Rust:

let x = 1;
x = "Hey! Now I am a string!";

would, again, result in a compile-time error: “mismatched types... expected integer, found &str”.

While dynamic typing is convenient, this does place additional responsibility on you the programmer. This is particularly true since Python, unlike many other languages, doesn’t care a whit about the types of formal parameters or return values of functions. Some languages ensure that programmers can’t write code that calls a function with arguments of the wrong type, or return the wrong type of value from a function. Python does not. Python won’t enforce the correct use of types—that’s up to you!

Original author: Clayton Cafiero < [given name] DOT [surname] AT uvm DOT edu >

No generative AI was used in producing this material. This was written the old-fashioned way.

This material is for free use under either the GNU Free Documentation License or the Creative Commons Attribution-ShareAlike 3.0 United States License (take your pick).