kkwiatkowski.dev

Hey, I'm Kamil. Welcome to my private place on the World Wide Web. You can find here entries, mostly about programming, technology, and web development, but sometimes also about life. Make yourself at home.

Python Type Hints - Introduction

Jan. 7, 2024, 2:40 p.m.

An Introduction

Python is a dynamically typed language, but what does that mean? Simply put, you don't have to declare variable types upfront because they are determined at runtime, not at compile time, which is the opposite of languages like C or Java, which are statically typed. Statically typed languages require programmers to clearly define data types for each variable before using it. Let's look at an example in C.

#include <stdio.h>

int main() {
    // Variable declarations
    int number = 10;          // Variable of type int
    float decimalNumber = 5.5;  // Variable of type float
    char character = 'A';     // Variable of type char

    // Displaying the values of variables
    printf("Integer number: %d\n", number);
    printf("Floating-point number: %.1f\n", decimalNumber);
    printf("Character: %c\n", character);

    return 0;
}

In Python, as you know, it looks different.

# In Python, you don't need to declare the type of a variable

# Variable declarations
number = 10          # Variable of type int
decimalNumber = 5.5  # Variable of type float
character = 'A'      # Variable of type char (in Python, char is treated as str)

# Displaying the values of variables
print("Integer number:", number)
print("Floating-point number:", decimalNumber)
print("Character:", character)

So, as you can see, in Python, you don't have to declare the type of a variable when you create it. Python understands on its own what data type has been passed to it and handles it accordingly. Besides, types can change dynamically, meaning the same variable can hold different types of data at different moments in the program's life. Dynamic typing makes Python more flexible and allows for writing code that is often shorter and more readable than in statically typed languages. Sounds great, and it is, but it also has its downsides. Errors related to data types are usually not detected until the program is run. For example, if you try to add a number to a string, Python will return an error, but only when that line of code is executed. Errors related to unexpected data types can be harder to detect and fix. That's why Python 3.5 introduced "type hints", which allow programmers to optionally specify expected data types, making code easier to understand and errors easier to catch.


What are Type Hints?

Type hints are a way to explicitly specify the types of data used in functions, methods, and variables. They are a form of code documentation that helps programmers understand what type of data should be passed to a function, what type of data a function returns, and what type of data a variable holds. It's an answer to the need for greater clarity in code in dynamically typed languages. Although Python manages data types on its own at runtime, type hints allow programmers to specify expected data types, facilitating both reading and later debugging of code. It's important to understand that these are just hints for other programmers and are not enforced at runtime. The Python interpreter does not enforce type compliance specified in type hints during code execution.

Why use them, then?

  1. Improving code readability and understandability.
  2. Facilitating static analysis and error detection before code execution.
  3. Easing refactoring and maintenance of code.
  4. It can also be said to facilitate communication in programming teams.

How to Use Type Hints?

Let's start again from the basics, in this case, the question - What types of data do we have in Python? Let's make a list:

  1. int - for integers, e.g., 5, 100, -3.
  2. float - for floating-point numbers, e.g., 5.0, 3.14.
  3. str - for strings, e.g., "hello", "kkwiatkowski.dev".
  4. bool - for boolean values, True or False.
  5. list - for lists, i.e., ordered collections, e.g., [1, 2, 3], ['a', 'b', 'c'].
  6. tuple - for tuples, which are immutable lists, e.g., (1, 2, 3).
  7. dict - for dictionaries, which store data in key-value pairs, e.g., {'name': 'Alice', 'age': 25}.
  8. set - for sets, which are unordered collections of unique elements, e.g., {1, 2, 3}.

Each of these data types can be used in type hints to increase the readability and safety of types in your code.
So, now that we've done a quick reminder, how do you use these type hints? What does the syntax look like?

Syntax

Variable Typing:To specify the type of a variable, use a colon (:) after the variable name, and then state the data type. For example, number: int = 5 means the variable number should be of type int.

Functions and Methods: In functions, type hints specify the types of parameters and the type of the return value. The type of a parameter is defined after its name, using a colon, and the return type is defined after an arrow (->) placed before the end of the function definition. For example, in the definition of the function def
add(a: int, b: int) -> int

a and b are of type int, and the function returns int.

For now, we will stop at typing variables, typing in functions, and methods. Maybe in some other next entry, I'll try to write something about more advanced use of typing. Here is the time and place for the basics :)

How to Use Type Hints for Different Types

1. Type Hints for Numbers (int, float)

def add_numbers(a: int, b: int) -> int:
    return a + b

2. Type Hints for Strings (str)

def greet(name: str) -> str:
    return f"Hello, {name}"

3. Type Hints for Lists (list)

def list_average(numbers: list[int]) -> float:
    return sum(numbers) / len(numbers)

4. Type Hints for Tuples (tuple)

def get_coordinates() -> tuple[int, int]:
    return (10, 20)

5. Type Hints for Dictionaries (dict)

def get_student(name: str) -> dict[str, str]:
    return {'name': name, 'course': "Python"}

6. Type Hints for Sets (set)

def unique_elements(elements: list[int]) -> set[int]:
    return set(elements)

 

To take full advantage of type hints in Python, it is recommended to use static code analysis tools such as Pylint, Mypy, or Pyright. These tools analyze your code for type compliance and other potential issues before the code is even run.

Pylint is a popular static analysis tool that can help detect errors in code, including those related to types. Although Pylint has some support for type hints, its main purpose is to ensure compliance with coding style conventions.

Mypy is an even more advanced tool, specifically designed to check type compliance using type hints in Python. Mypy can thoroughly analyze your code for type compliance and inform you of potential problems.

Pyright is another static type analysis tool for Python, designed by Microsoft. It is known for its speed and efficiency, and it also offers support for type hints.

I personally use Pylint.

 

Although Python remains a dynamically typed language, type hints allow the use of the advantages of static typing, while maintaining the flexibility and ease of coding for which Python is valued. It is therefore worth considering their use in your projects, especially when working in larger teams or on more complex applications.

That's all for today.