4

I just discovered function annotations for python 3 (https://www.python.org/dev/peps/pep-3107/) which seems great for documenting parameters or return types. It also makes better intellisense available in my pycharm IDE.

I have a question regarding parameters where the input type is fuzzy. For example, it could be a list or numpy array or some "array-like" quantity. What is the best way to annotate such an input parameter to the function? Example:

import numpy as np

def fun(data: np.ndarray) # can also be a list
    pass

I have another case where the input can be any of the two types. Example:

def fun(header: Nifti1Header) # can also be Nifti2Header
    pass

What is the best way to document these kinds of parameter inputs?

Luca
  • 10,458
  • 24
  • 107
  • 234

2 Answers2

5

If you are using python3.5, the best way is to use typing.Union

>>> from typing import Union
>>> import numpy as np
>>> def fun(data: Union[np.ndarray, list]):
        pass

You could alternatively use typing.TypeVar if you are consistently using Union[t1, t2, ...]. (Plus you can add and delete types from the TypeVar more easily than many Unions in your code)

>>> from typing import TypeVar
>>> import numpy as np
>>> import array
>>> Ar = TypeVar('Ar', np.ndarray, list, array.array)

This code would then associate Ar with lists, array.arrays, and numpy arrays.

Edward Minnix
  • 2,889
  • 1
  • 13
  • 26
4

You'll have to work out what common property the legal inputs for you function share. For the first one, it looks like it should be iterable:

>>> from collections import Iterable
>>> def fun(data: Iterable):
...     pass
... 
>>> isinstance(np.ndarray(0), Iterable)
True
>>> isinstance([], Iterable)
True
>>> isinstance(23, Iterable)
False

For your headers, it smells like Nifti1Header and Nifti2Header should inherit from a common base class. If the function should work for any derived class, why not annotate it with the base class?

timgeb
  • 76,762
  • 20
  • 123
  • 145