Posted at

Pythonの基本的な型の階層構造を図にしてみた

GeneratorがSequenceでないことに少し疑問に思ったこともあり

Pythonの基本的な型の階層構造をGraphvizを使って図にしてみました。

type_hierarchy.png

生成に使ったコードは以下


type_check.py

from typing import *

from typing import IO, BinaryIO, TextIO
import collections
import datetime
import enum
import numbers
import decimal
import fractions
from itertools import groupby
from more_itertools import first
from graphviz import Digraph

G = Digraph(format='png')
types = [
TypeVar,
# Generic,
Type, Iterable, Iterator, Reversible, SupportsInt, SupportsFloat, SupportsComplex, SupportsBytes, SupportsAbs,
SupportsRound, Container, Hashable, Sized, Collection, AbstractSet, MutableSet, Mapping, MutableMapping, Sequence,
MutableSequence, ByteString, Deque, List, Set, FrozenSet, MappingView, KeysView, ItemsView, ValuesView, Awaitable,
Coroutine, AsyncIterable, AsyncIterator, ContextManager, Dict, DefaultDict, Counter, ChainMap, Generator,
AsyncGenerator, Text, IO, TextIO, BinaryIO,
# Pattern,
# Match,
NamedTuple,
# Any,
# Union,
# Optional,
Tuple, Callable,
# ClassVar,
# AnyStr
collections.OrderedDict,
int, float, complex, range, bytes, bytearray, memoryview,
datetime.date, datetime.time, datetime.datetime, datetime.timedelta, datetime.tzinfo, datetime.timezone,
enum.Enum, enum.IntEnum, enum.IntFlag, enum.Flag,
numbers.Complex, numbers.Real, numbers.Rational, numbers.Integral,
decimal.Decimal, decimal.Context,
fractions.Fraction
]

subtype_pairs = [(t1, t2) for t1 in types for t2 in types if t1 is not t2 if issubclass(t1, t2)]
for t1, t2_list in groupby(subtype_pairs, first):
t2_list = list(t2_list)
for _, t2 in t2_list:
if not any([issubclass(x, t2) for _, x in t2_list if x is not t2]):
G.edge(t1.__name__, t2.__name__)

G.render('type_hierarchy')


ちなみに、Anaconda/Windows環境だからなのか、動作させるためにはPythonのgraphvizパッケージだけでなく、python-graphvizパッケージも必要でした。