Modern typing starting from Python 3.8 vol.1 (without class)

introduction

I recently read O'Reilly's Programming TypeScript and was very impressed. The depth and fun of Generics, the increase in function and object information due to the presence of types, and the sense of security that is created. I have become anxious and unable to take a nap without a mold.

At that time, I decided to announce it at "Hida Takayama Python Mokumokukai" this month as well, and I thought that it was almost out of material. That's right, it's fun to announce with TypeScript that impressed me.

Fortunately Python also has type hints. I thought Python's type system was a bit poorer than TypeScript, but when I looked it up, why? It had all the useful features (especially after 3.8)

In this article, I would like to convey the depth, fun and convenience of the type system through the series.

I completely covered it

When I wrote it halfway, when I was watching the PyCon JP2020 program, " Python 3.9 How to master type-safe Python in the era by. Mitsuki Ogasawara ”isn't it? I thought it was done, but I wrote it so I decided to go as it is. Not everyone writes the same thing. Partially referred to the notation after 3.9 and reflected in this content.

Target audience

Some of these people may imagine this when it comes to patterns. The existence of the mold increases muscular strength (performance), but the programming is forced to be stiff and restricted in movement. But that's not the case. The molds are programmable and productive. If you read it to the end, you will surely understand it. No, I can understand. I think I can do it. …… I will do my best to write it so that you can understand it.

I think these people also have new discoveries. It was surprisingly interesting to type the dynamic language afterwards. That's TypeScript and type hints. Even those who have a lot of linguistic experience may be surprised and discover the interesting mechanism of Union type and Literal type.

Characteristics of Python type hints

This section describes the characteristics of Python type hints and the uses that can be seen from those characteristics.

Type information is completely ignored at run time

Type information is ignored at run time. So

It's kind of a subtle thing at first glance, so to speak, ** type hints are just comments **. …… I can see that your motivation is going down. However, if you look at the type hints as ** comments **, the intensity of them becomes apparent.

How is it, isn't it interesting to think so? And it will look very powerful. ** In fact, it's powerful **.

By the way, I think that everyone's motivation has recovered a little. Let's get into practice now.

Prepare in advance with VS Code

This time I experimented with VS Code and Pyright. To put pyright in VSCode and configure it, see below.  https://qiita.com/simonritchie/items/33ca57cdb5cb2a12ae16

When you put it in, it looks like this. Annoying wavy lines come out. Screenshot from 2020-09-06 11-57-46.png To put it the other way around, this annoying wavy line is the ultimate advantage of using type hints.

How to write a type

Variable name:Mold=value

Basic type

int: Integer type

i: int = 2
i = 1.1 ##type error! # 1.1 is a float so an error

If you put a different type of variable in the typed variable, an annoying wavy line will appear. It's annoying so let's fix it.

float: floating point

f: float = 1.0
f = 1 #1 is int type, but cast(Type conversion)Does not result in an error

complex: complex type

c: complex = 1 + 2j

str: String type

s: str = 'hoge'

byte: byte array

byte: bytes = b'test'

bool: Boolean value

b: bool = True

Type that takes a type argument

The types introduced here are great types that take other types as type arguments (like arguments). So to speak, type abstraction and programming. Describe using typing.

import typing

The notation is as follows.

Variable name:Model name[Type argument] =value

list: list

lst: typing.List[int] = [1, 2, 3] 
lst2: list[int] = [0,1,2] # Python3.Notation that can be used after 9

If you're wondering if you can make a list with a little more freedom, it will come out later.

set: unique list

st: typing.Set[int] = {1, 2, 3}

tuple: Fixed length array with specified type and length

List all types.

tpp: typing.Tuple[int, bool, str] = (1, True, 'test')

dict: dictionary

Dict [key type, value type]

dic: typing.Dict[str, int] = {'name': 1, 'age': 2}
dic1: dict[str, int] = {'test': 1} # Python3.Notation that can be used after 9

This is good news for those who think that complicated dictionaries cannot be used. Later, there will be a way to specify more finely.

Type alias

I think it was around the time when I thought that type information was a long time. There are type aliases that can be called variable versions of types for those who are impatient, or for those who are pragmatic who want to give names to the types they have created and manage them in an easy-to-understand manner.

TupleIBS = typing.Tuple[int, bool, str]

Selectable type

Union: Enumeration

Union [Type 1, Type 2, Type 3 ...] It can be any of the types listed in the type argument.

uni: typing.Union[int, bool] = 1
uni = False
uni3: int | bool = 1 # Python3.Notation that can be used from 10

The molds can be combined for even greater effect. Earlier I mentioned a more flexible list. Let's do it here.

list_ib: typing.List[typing.Union[int, bool]] = [1, True, 2, False]

Literal: Literal type (* Python 3.8 or later)

It is a divine function. ~~ It's a divine function so you don't understand why there aren't many mentions in Japanese-speaking countries. Are you licking? ~~ There was a mention in the performance of PyCon JP2020. In a nutshell, it's a constant type. You can have a more limited type expression. In addition, there is an enumeration function. strong.

li1: typing.Literal[1] = 1 #Real constant
li2: typing.Literal['hoge', 'fuga'] = 'fuga' #Multiple descriptions are possible
li2 = 'hoge'

Final (* Python 3.8 or later)

You can express immutable (universal). However, there are some pitfalls.

c: typing.Final[str] = 'c'
c = 'a' ##type error!
lis: typing.Final[typing.List[int]] = [1,2,3]
lis[1] = 1 #No error

Well, let's use tuple obediently in such cases.

TypedDict: Typed dictionary (* Python 3.8 or later)

You can specify the dictionary more finely. And if you read this carefully and actually write it, you will find the convenience of the type system.

#Write dictionary type information using class notation
class UserDict (typing.TypedDict): #Inherit TypedDict
    name: str
    age: Optional[int] #None Enable ≒ Union[int, None]
    sex: typing.Literal['men', 'women', 'other']

users: typing.List[UserDict] = [
    {
        'name': 'noji', #String only
        'age': 33,      #Numerical or None only
        'sex': 'men'    #"Han" cannot be entered. Input assistance is also effective.
    },
    {
        'name': 'superwomen',
        'age': None,
        'sex': 'women'
    }
]

Summary: Let's enjoy with the mold

This time, I explained the basic (almost no classes) basic types. I think you can see the meaning of the type being programmable and a useful comment that also works for the IDE. Even if you just think of it, you can think of it as ** narrowing down the choices of dictionary types and arguments **. The Literal type is very useful when you want to specify options as strings. It will also reduce your worries when picking up and using JSON whose form is known. If you know the type, intellisense will work, so it is perfect even when using a class you are not familiar with. I'm glad that I can flexibly type because I typed a language that originally had no type.

With a mold, you can have a lot of fun with a little effort. It is a great help to master the ** laziness ** of the programmer's three great virtues. Now, let's do easy and fun programming with molds.

Appendix: When suffering from mold

But it's crazy. Sometimes I suffer from molds. I just want to write logic, why am I fighting this type error? Like. In such a case, let's think that it is okay to compromise.

Type inference

As long as you don't rewrite the variable even once, ** type inference ** works effectively, so you don't have to bother to write the type. As a matter of fact, I also write only the following type information.

boo = True #The IDE automatically infers that it is a bool type and acts shaved on it
boo = 1 #However, the type changes (or becomes Any) at the moment of rewriting.

cast: type conversion

If you don't have the type information or are in trouble, try using it. Why is it so useful? Abuse is strictly prohibited as it can be forcibly converted.

i3: int = typing.cast(int, 1.0)

Any: Anything type

This is the world of Python without type hints. It is quite a powerful drug.

ani: typing.Any = 1
ani = 'hoge'
ani = ['fuga', 129999, True]

Recommended Posts

Modern typing starting from Python 3.8 vol.1 (without class)
"Python AI programming" starting from 0 for windows
Business efficiency starting from scratch with Python
Generate a class from a string in Python
Python typing
Python explosive environment construction starting from zero (Mac)
Registering with PyPI from modern Python library self-made
[Python] class, instance
About python, class
Python dynamic typing
sql from python
[Python] Understand the self of the class. Learn the role of self from the execution result with or without self.
MeCab from Python
Python class, instance
#Python basics (class)
[Python] Django Source Code Reading View Starting from Zero ①
Introduction to Mathematics Starting with Python Study Memo Vol.1