Python is a “dynamically typed language,” meaning you can write code without declaring variable types (integer, string, etc.). While this flexibility is appealing, it can cause confusion in large-scale or team development, such as “What kind of data should I pass to this function?” or “What is the return value?”, leading to bugs.
To address this, Python 3.5 introduced “Type Hints.” This feature allows you to describe the “expected type” for variables, function arguments, and return values as annotations. This article explains the basic syntax of type hints and their benefits.
What are Type Hints?
Type hints are merely “hints” and are ignored during Python execution. Even if the types differ, no error will occur, and the program will run. However, by using editors like VS Code or PyCharm, or static analysis tools (like mypy), you can get warnings like “Type mismatch” while writing code, allowing you to prevent bugs before they happen.
Type Annotations for Variables
When defining a variable, write : TypeName after the variable name.
# Example defining game character status
# String type (str)
hero_name: str = "Arthur"
# Integer type (int)
current_hp: int = 2500
# Boolean type (bool)
is_poisoned: bool = False
print(f"Name: {hero_name} (HP: {current_hp}) Poisoned: {is_poisoned}")
Writing code this way clearly indicates the intent that “current_hp should contain a number and not a string” directly in the code.
Type Annotations for Functions
You can also specify types for function arguments and return values.
- Argument:
argument_name: TypeName - Return Value:
def function_name(...) -> TypeName:
Specific Code Example
Let’s create a function that accepts attack and defense power, calculates damage, and returns the result message (string).
def calculate_battle_result(attacker_atk: int, target_def: int, is_critical: bool) -> str:
"""
Function to create a battle result message
"""
# Damage calculation (simple subtraction)
damage = attacker_atk - target_def
# Double damage if critical hit
if is_critical:
damage *= 2
# Ensure damage is not negative
if damage < 0:
damage = 0
return f"Dealt {damage} damage to the enemy!"
# --- Calling the function ---
# Calling with correct types
# Attack: 100, Defense: 40, Critical: True
message = calculate_battle_result(100, 40, True)
print(message)
# (Reference) Execution is possible even with different types, but the editor will warn you
# error_call = calculate_battle_result("Strongest", 50, "yes")
Output:
Dealt 120 damage to the enemy!
Explanation
def calculate_battle_result(attacker_atk: int, target_def: int, is_critical: bool) -> str:
attacker_atk: int: Expects attack power to be an integer.target_def: int: Expects defense power to be an integer.is_critical: bool: Expects critical hit judgment to be a boolean.-> str: Indicates that this function ultimately returns a message (string).
Specifying Complex Types (list, dict, Union, Optional)
You can express not only simple types but also the contents of lists and dictionaries, or cases where “multiple types are possible.” For this, use the typing module (or standard built-in types in Python 3.9+).
from typing import List, Dict, Union, Optional
# List of integers (e.g., score history)
high_scores: List[int] = [5000, 8200, 10500]
# In Python 3.9+, you can write list[int] = [...]
# Allow string or integer (Union) - e.g., ID
player_id: Union[int, str] = "P-999"
# In Python 3.10+, you can write int | str = "P-999"
# Allow string or None (Optional) - e.g., Guild name
guild_name: Optional[str] = None
Summary
- Using type hints allows you to explicitly state the “expected type” of variables and functions.
- Write in the format
variable: typeordef func(...) -> return_type:. - While it doesn’t affect runtime behavior, combining it with editor completion and static analysis tools dramatically improves development efficiency and code quality.
