DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

Type hints in Python (3)

Buy Me a Coffee

*Memo:

A lambda cannot have type hints as shown below:

lam = lambda x: str: x -> str
lam = lambda x: str: x
lam = lambda x: x -> str
# error: Invalid syntax
Enter fullscreen mode Exit fullscreen mode

Using --strict, the variable without a type hint doesn't get error except a lambda while the function without type hints gets the errors as shown below:

*Memo:

  • Error doesn't occur whether self has a type hint or not in the method which is the function within a class.
  • The reason why the variable without a type hint doesn't get error (except a lambda) is because always needing to type-hint a variable is too strict and too much, needing to write more code, making code complicated:
    • A lambda cannot have type hints so its variable must have a type hint.
  • Not using --strict, both the variable and function without type hints don't get error.
v = 'Hello'
# No error
Enter fullscreen mode Exit fullscreen mode
lam = lambda x: x

lam()
# error: Call to untyped function (unknown) in typed context
Enter fullscreen mode Exit fullscreen mode
def func(x):
    return x
# error: Function is missing a type annotation
Enter fullscreen mode Exit fullscreen mode
def func(x) -> str:
    return x
# error: Function is missing a type annotation for one or more arguments
Enter fullscreen mode Exit fullscreen mode
def func(x: str):
    return x
# error: Function is missing a return type annotation
Enter fullscreen mode Exit fullscreen mode
class Cls:
            # ↓↓↓↓↓↓↓↓↓ With a type hint
    def func1(self: Cls) -> None:
        return None

            # ↓↓↓↓ Without a type hint
    def func2(self) -> None:
        return None
# No error
Enter fullscreen mode Exit fullscreen mode

Type checkers infer the type of the non-type-hinted variable outside a function from the assigned value, and infer the types of the non-type-hinted parameter(including *args, **kwargs or self), variable and return value within a function as Any as shown below:

*Memo:

  • reveal_type() can ask a type checker to print the static type of a value:
    • The 1st argument is obj(Required-Type:Any):
      • It's a value.
      • Don't use obj=.
    • At runtime, it prints the runtime type of a value.
  • The doc explains type inference.
  • mypy test.py is used.
from typing import reveal_type

# `v` is `int`
v = 100
reveal_type(v) # builtins.int (Runtime type is 'int')

v = 200  # No error
v = 3.14 # Error
Enter fullscreen mode Exit fullscreen mode
from typing import reveal_type

# The type of `x`, `y` and return value are `Any`.
def func(x=100, *args, **kwargs):
    reveal_type(x) # Any (Runtime type is 'int')

    x = 200  # No error
    x = 3.14 # No error

    reveal_type(args) # Any (Runtime type is 'tuple')

    x = 200  # No error
    x = 3.14 # No error

    reveal_type(kwargs) # Any (Runtime type is 'dict')

    x = 200  # No error
    x = 3.14 # No error

    y = 100
    reveal_type(y) # Any (Runtime type is 'int')

    y = 200  # No error
    y = 3.14 # No error

    return 100

v = func()

reveal_type(v) # Any (Runtime type is 'int')

v = 200  # No error
v = 3.14 # No error
Enter fullscreen mode Exit fullscreen mode
from typing import reveal_type

# The type of `v`, `self`, `x` and return value are `Any`.
class Cls:
    v = 100
    reveal_type(v) # builtins.int (Runtime type is 'int')

    v = 200  # No error
    v = 3.14 # Error

    def func(self, x):
        reveal_type(self) # Any (Runtime type is 'Cls')

        self = 200  # No error
        self = 3.14 # No error

        reveal_type(x) # Any (Runtime type is 'int')

        x = 200  # No error
        x = 3.14 # No error

cls = Cls().func(100)

reveal_type(cls) # Any (Runtime type is 'NoneType')

cls = 200  # No error
cls = 3.14 # No error
Enter fullscreen mode Exit fullscreen mode

assert_type() can ask a type checker to check if the static type of val is typ as shown below:

*Memo:

  • The 1st argument is val(Required-Type:Any):
    • It's a value.
    • Don't use val=.
  • The 2nd argument is typ(Required-Type:Type):
    • It's a type.
    • Don't use typ=.
  • Error occurs if the static type of val isn't typ while nothing happens if the static type of val is typ.
  • At runtime, it returns the 1st argument.
from typing import assert_type

v: int = 100
assert_type(v, int)   # No error(No message)
assert_type(v, float) # Error
Enter fullscreen mode Exit fullscreen mode

cast can cast the static type of a value to other (or same) static type as shown below:

*Memo:

  • The 1st argument is typ(Required-Type:Any):
    • It's a type.
    • Don't use typ=.
  • The 2nd argument is val(Required-Type:Type):
    • It's a value.
    • Don't use val=.
  • At runtime, it does nothing.
from typing import reveal_type, cast

v1: int = 100

v1 = 200 # No error

# `int` is casted to `float`.
v2 = cast(float, v1)
reveal_type(v2) # builtins.float (Runtime type is 'int')

v2 = 3.14 # No error
Enter fullscreen mode Exit fullscreen mode

Top comments (0)