When you’re puzzled or when things are complicated

  1. from typing import Union, Any, List, Optional, cast
  2.  
  3. # To find out what type mypy infers for an expression anywhere in
  4. # your program, wrap it in reveal_type(). Mypy will print an error
  5. # message with the type; remove it again before running the code.
  6. reveal_type(1) # -> Revealed type is 'builtins.int'
  7.  
  8. # Use Union when something could be one of a few types
  9. x = [3, 5, "test", "fun"] # type: List[Union[int, str]]
  10.  
  11. # Use Any if you don't know the type of something or it's too
  12. # dynamic to write a type for
  13. x = mystery_function() # type: Any
  14.  
  15. # If you initialize a variable with an empty container or "None"
  16. # you may have to help mypy a bit by providing a type annotation
  17. x = [] # type: List[str]
  18. x = None # type: Optional[str]
  19.  
  20. # This makes each positional arg and each keyword arg a "str"
  21. def call(self, *args, **kwargs):
  22. # type: (*str, **str) -> str
  23. request = make_request(*args, **kwargs)
  24. return self.do_api_query(request)
  25.  
  26. # Use a "type: ignore" comment to suppress errors on a given line,
  27. # when your code confuses mypy or runs into an outright bug in mypy.
  28. # Good practice is to comment every "ignore" with a bug link
  29. # (in mypy, typeshed, or your own code) or an explanation of the issue.
  30. x = confusing_function() # type: ignore # https://github.com/python/mypy/issues/1167
  31.  
  32. # "cast" is a helper function that lets you override the inferred
  33. # type of an expression. It's only for mypy -- there's no runtime check.
  34. a = [4]
  35. b = cast(List[int], a) # Passes fine
  36. c = cast(List[str], a) # Passes fine (no runtime check)
  37. reveal_type(c) # -> Revealed type is 'builtins.list[builtins.str]'
  38. print c # -> [4]; the object is not cast
  39.  
  40. # If you want dynamic attributes on your class, have it override "__setattr__"
  41. # or "__getattr__" in a stub or in your source code.
  42. #
  43. # "__setattr__" allows for dynamic assignment to names
  44. # "__getattr__" allows for dynamic access to names
  45. class A:
  46. # This will allow assignment to any A.x, if x is the same type as "value"
  47. # (use "value: Any" to allow arbitrary types)
  48. def __setattr__(self, name, value):
  49. # type: (str, int) -> None
  50. ...
  51.  
  52. a.foo = 42 # Works
  53. a.bar = 'Ex-parrot' # Fails type checking