$ python3 -m mypy --strict example.py
def subtract(a: int, b:int) -> int:
return a-b
subtract(10, '5')
$ python3 -m mypy --strict example.py
.../example.py: error: Argument 2 to "subtract" has incompatible type "str"; expected "int"
class Counter:
def __init__(self) -> None:
self.value: int = 0 # 필드/변수 annotation
def add(self, offset: int) -> None:
value += offset # 헉. 'self.'를 안썼다..
def get(self) -> int:
self.value # 헉. 'return'을 안썼다..
counter = Counter()
counter.add(5)
counter.add(3)
assert counter.get() == 8
$ python3 -m mypy --strict example.py
.../example.py:6: error: Name 'value' is not defined
.../example.py:8: error: Missing return statement
from typing import Callable, List, TypeVar
Value = TypeVar('Value') # Can be anything
Func = Callable[[Value, Value], Value]
def combine(func: Func[Value], values: List[Value]) -> Value:
assert len(values) > 0
result = values[0]
for next_value in values[1:]:
result = func(result, next_value)
return result
Real = TypeVar('Real', int, float)
def add(x: Real, y: Real) -> Real:
return x + y
inputs = [1, 2, 3, 4j]
result = combine(add, inputs)
assert result == 10
$ python3 -m mypy --strict example.py
.../example.py:21: error: Argument 1 to "combine" has incompatible type "Callable[[Real, Real], Real]"; expected "Callable[[complex, complex], complex]"
Typing
사용법typing.Type
사용법typing.TypeVar
사용법TypeVar는 제네릭 타입을 만들 때 사용하는 클래스입니다.
제네릭 타입?
제네릭 타입은 클래스나 함수에서 사용할 데이터 타입을 나중에 지정할 수 있는 타입입니다.
제네릭 타입을 사용하면 데이터 타입에 대한 추상화 수준을 높일 수 있으며, 코드 재사용성과 유연성을 높일 수 있습니다.
제네릭 타입은 다음과 같은 장점을 가집니다.
제네릭 타입은 다양한 프로그래밍 언어에서 지원됩니다.
Python에서도 제네릭 타입을 지원하며, typing 모듈을 사용하여 제네릭 함수나 클래스를 정의할 수 있습니다.
예를 들어, List, Tuple, Dict 등은 제네릭 타입으로 정의되어 있으며, 다양한 데이터 타입의 요소를 저장할 수 있습니다.
TypeVar를 사용하면 타입 어노테이션에서
TypeVar 클래스를 사용하는 방법은 다음과 같습니다.
from typing import TypeVar
T = TypeVar('T') # Can be anything
S = TypeVar('S', bound=str) # Can be any subtype of str
A = TypeVar('A', str, bytes) # Must be exactly str or bytes
U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes
# SupportsAbs -> abstract types (ABCs or protocols)
V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
typing.Callable
사용법Callable[[int], str]
is a function of (int) -> str....
Callable[..., ReturnType]
은 범용적으로 쓰일 수 있다.Callable
= Callable[..., Any]
= collections.abc.Callabletyping.Optional
사용법typing.Optinal[X]
== typing.Union[X, None]
from typing import Optional
def get_or_default(value: Optional[int], default: int) -> int:
if value is not None:
return value
return default
typing.Union
사용법typing.Union[X, Y]
== X|Y
(얜 파이썬 3.10부터 사용가능 ㅠ)collections.abc
사용법collections.abc.Mapping
collections.abc.Mapping
or collections.abc.MutableMapping
abstract base classes. dict
, collections.defaultdict
, collections.OrderedDict
and collections.Counter
.from collections.abc import Mapping, Sequence
from typing import Any
def keys(mapping: Mapping[str, Any]) -> Sequence[str]:
return tuple(mapping)
collections.abc.Sequence
An iterable which supports efficient element access using integer indices via the __getitem__()
special method and defines a __len__()
method that returns the length of the sequence.
Some built-in sequence types are list
, str
, tuple
, and bytes
.
Note that dict also supports __getitem__()
and __len__()
, but is considered a mapping rather than a sequence because the lookups use arbitrary immutable keys rather than integers.
The collections.abc.Sequence abstract
base class defines a much richer interface that goes beyond just __getitem__()
and __len__()
, adding count()
, index()
, __contains__()
, and __reversed__()
.
Types that implement this expanded interface can be registered explicitly using register()
.
collections.abc.Callable
__call__()
method.from collections.abc import Callable
def instantiate(factory: Callable[[], int]) -> int:
return factory()
NameError: name `SecondClass` is not defined
class FirstClass:
def __init__(self, value: 'SecondClass') -> None:
self.value = value
from __future__ import annotations
# 프로그램 실행 시, type annotation 에 지정된 값을 완전히 무시하라고 지시한다.
class FirstClass:
def __init__(self, value: SecondClass) -> None:
self.value = value