Optional types and the None type

You can use the Optional type modifier to define a type variantthat allows None, such as Optional[int] (Optional[X] isthe preferred shorthand for Union[X, None]):

  1. from typing import Optional
  2.  
  3. def strlen(s: str) -> Optional[int]:
  4. if not s:
  5. return None # OK
  6. return len(s)
  7.  
  8. def strlen_invalid(s: str) -> int:
  9. if not s:
  10. return None # Error: None not compatible with int
  11. return len(s)

Most operations will not be allowed on unguarded None or Optionalvalues:

  1. def my_inc(x: Optional[int]) -> int:
  2. return x + 1 # Error: Cannot add None and int

Instead, an explicit None check is required. Mypy haspowerful type inference that lets you use regular Pythonidioms to guard against None values. For example, mypyrecognizes is None checks:

  1. def my_inc(x: Optional[int]) -> int:
  2. if x is None:
  3. return 0
  4. else:
  5. # The inferred type of x is just int here.
  6. return x + 1

Mypy will infer the type of x to be int in the else block due to thecheck against None in the if condition.

Other supported checks for guarding against a None value includeif x is not None, if x and if not x. Additionally, mypy understandsNone checks within logical expressions:

  1. def concat(x: Optional[str], y: Optional[str]) -> Optional[str]:
  2. if x is not None and y is not None:
  3. # Both x and y are not None here
  4. return x + y
  5. else:
  6. return None

Sometimes mypy doesn’t realize that a value is never None. This notablyhappens when a class instance can exist in a partially defined state,where some attribute is initialized to None during objectconstruction, but a method assumes that the attribute is no longer None. Mypywill complain about the possible None value. You can useassert x is not None to work around this in the method:

  1. class Resource:
  2. path: Optional[str] = None
  3.  
  4. def initialize(self, path: str) -> None:
  5. self.path = path
  6.  
  7. def read(self) -> str:
  8. # We require that the object has been initialized.
  9. assert self.path is not None
  10. with open(self.path) as f: # OK
  11. return f.read()
  12.  
  13. r = Resource()
  14. r.initialize('/foo/bar')
  15. r.read()

When initializing a variable as None, None is usually anempty place-holder value, and the actual value has a different type.This is why you need to annotate an attribute in a cases like the classResource above:

  1. class Resource:
  2. path: Optional[str] = None
  3. ...

This also works for attributes defined within methods:

  1. class Counter:
  2. def __init__(self) -> None:
  3. self.count: Optional[int] = None

As a special case, you can use a non-optional type when initializing anattribute to None inside a class body and using a type comment,since when using a type comment, an initializer is syntactically required,and None is used as a dummy, placeholder initializer:

  1. from typing import List
  2.  
  3. class Container:
  4. items = None # type: List[str] # OK (only with type comment)

This is not a problem when using variable annotations, since no initializeris needed:

  1. from typing import List
  2.  
  3. class Container:
  4. items: List[str] # No initializer

Mypy generally uses the first assignment to a variable toinfer the type of the variable. However, if you assign both a Nonevalue and a non-None value in the same scope, mypy can usually dothe right thing without an annotation:

  1. def f(i: int) -> None:
  2. n = None # Inferred type Optional[int] because of the assignment below
  3. if i > 0:
  4. n = i
  5. ...

Sometimes you may get the error “Cannot determine type of <something>”. In thiscase you should add an explicit Optional[…] annotation (or type comment).

Note

None is a type with only one value, None. None is also usedas the return type for functions that don’t return a value, i.e. functionsthat implicitly return None.

Note

The Python interpreter internally uses the name NoneType forthe type of None, but None is always used in typeannotations. The latter is shorter and reads better. (Besides,NoneType is not even defined in the standard library.)

Note

Optional[…] does not mean a function argument with a default value.However, if the default value of an argument is None, you can usean optional type for the argument, but it’s not enforced by default.You can use the —no-implicit-optional command-line option to stoptreating arguments with a None default value as having an implicitOptional[…] type. It’s possible that this will become the defaultbehavior in the future.