Everyone. Are you writing in Python? Recently, I have reaffirmed the importance of types, so I wrote this article with the hope that everyone would write types in Python.
As a caveat, this article does not mention the following:
This content is a supplement to the article I wrote earlier, so please refer to the previous article if you like.
Practice! !! Introduction to Python Type (Type Hints)
Python is a dynamically typed language, so your program will work without writing any types. By not writing the type, the amount of code is reduced, and I think it is an advantage that the language is easy for beginners to learn. However, when writing a certain number of lines of code, when maintaining a program by multiple people, the following problems occur if there is no type.
So, from the perspective of maintaining a program for a long period of time, I think that having a type has an advantage.
For example, consider the following function.
def add(a, b):
"""Returns the result of adding arguments"""
return a + b
def add_type(a: int, b: int) -> int:
"""Returns the result of adding arguments"""
return a + b
Functions with the same content, but one has a type and the other has no type. You can actually use it like this, but if the creator of the function didn't expect it to contain a string, the add_type function with a type will display an error in the editor.
print(add('1', '2'))
print(add_type('1', '2'))
The creator and user of a function are not always the same, and even a function you create will forget its contents over time. By giving a type, you can expect the function to be used as you expected.
Regarding list etc., the writing method is different between Python 3.8 and 3.9. The traditional typing method has been deprecated and the built-in type method has been recommended.
For Python 3.8
from typing import Dict, List, Tuple
val_e: Dict[str, int] = {'size': 12, 'age': 24}
val_f: List[str] = ['taro', 'jiro']
val_g: Tuple[str, int] = ('name', 12)
For Python 3.9
val_e: dict[str, int] = {'size': 12, 'age': 24}
val_f: list[str] = ['taro', 'jiro']
val_g: tuple[str, int] = ('name', 12)
Final has been available by default since Python 3.8. You can prevent it from being reassigned by defining a constant (not reassignable).
from typing import Final
TABLE_NAME: Final[str] = 'sample'
I get an error when I try to reassign.
Since list and tuple have similar functions, I tend to use list, but tuple may have more advantages, so I will introduce it. In the case of list, it is possible to rewrite the internal information, but in most cases, what is defined as a constant does not want the internal information to be rewritten. In such a case, if you define it with tuple, you do not have to worry about the internal information being changed.
For Python 3.8
from typing import Final, Tuple, List
#Since it is a tuple, it cannot be changed.
NAME_TUPLE: Final[Tuple[str, str]] = ('taro', 'jiro')
#list can be changed
NAME_LIST: Final[List[str]] = ['taro', 'jiro']
NAME_LIST[0] = 'saburo'
For Python 3.9
from typing import Final
#Since it is a tuple, it cannot be changed.
NAME_TUPLE: Final[tuple[str, str]] = ('taro', 'jiro')
#list can be changed
NAME_LIST: Final[list[str]] = ['taro', 'jiro']
NAME_LIST[0] = 'saburo'
I think there are cases where dict is used for constants. In that case, you can rest assured that using namedtuple will not change the internal information.
from typing import NamedTuple, TypedDict
class StudentInfoTuple(NamedTuple):
name: str
age: int
class StudentInfoDict(TypedDict):
name: str
age: int
#In case of namedtuple, internal information cannot be rewritten
TARO: Final[StudentInfoTuple] = StudentInfoTuple('taro', 12)
#The following line will result in an error
# TARO.name = 'taro2'
#In the case of dict, internal information can be rewritten
JIRO: Final[StudentInfoDict] = {'name': 'jiro', 'age': 9}
JIRO['name'] = 'jiro2'
First, there are two ways to write TypedDict. In the example below, MovieA and MovieB can be used as synonymous types.
from typing import TypedDict
MovieA = TypedDict('MovieA', {'name': str, 'year': int})
class MovieB(TypedDict):
name: str
year: int
cat: MovieA = {'name': 'cat', 'year': 1993}
dog: MovieB = {'name': 'dog', 'year': 2000}
So what if you want to consider whether a type called Movie has an attribute called author or not? In that case, write as follows.
from typing import TypedDict
class MovieRequiredType(TypedDict):
name: str
year: int
class MovieOptionalType(TypedDict, total=False):
author: str
class MovieType(MovieRequiredType, MovieOptionalType):
pass
#MovieType may or may not have the author attribute
rabbit: MovieType = {'name': 'rabbit', 'year': 2002}
deer: MovieType = {'name': 'deer', 'year': 2006, 'author': 'jack'}
Of course, if there are no required attributes name and year, an error will occur on the editor.
There are two ways to write TypedDict, but the class style has an advantage in that it can be inherited multiple times. Therefore, I think that there are many people who actively use this.
I hope you understand the importance of types in Python. Writing types can seem daunting, but the more complex your code, the more you'll understand the value of types. Last but not least, Python 3.9 notation is not supported by some tools (such as mypy), so please be careful when using it. (As of October 2020)
Recommended Posts