pythonpycharmpython-typing

Python typing: declare type of callable when give it instance method


Consider the following code:

import typing

def a(x: int, y: int) -> int:
    return x + y

class F(object):
    def b(self, x: int, y: int) -> int:
        return x + y

def call(operation: typing.Callable[[int, int], int]) -> int:
    return operation(2, 2)

call(a)

f = F()
call(f.b)

My PyCharm IDE indicates a typing error for the last line:

1

Is it a typing/type declaration error? Is the PyCharm type checker failing? If it's a typing error, what should it be?


Solution

  • This is a PyCharm typechecker bug. The mypy typechecker accepts your example without warnings or errors:

    $ bin/mypy --verbose so_41869174.py
    LOG:  Mypy version 0.470
    LOG:  Parsing so_41869174.py (so_41869174)
    LOG:  Parsing lib/mypy/typeshed/stdlib/3/typing.pyi (typing)
    LOG:  Parsing lib/mypy/typeshed/stdlib/3/builtins.pyi (builtins)
    LOG:  Parsing lib/mypy/typeshed/stdlib/3/sys.pyi (sys)
    LOG:  Parsing lib/mypy/typeshed/stdlib/3/abc.pyi (abc)
    LOG:  Parsing lib/mypy/typeshed/stdlib/3/types.pyi (types)
    LOG:  Parsing lib/mypy/typeshed/third_party/2and3/mypy_extensions.pyi (mypy_extensions)
    LOG:  Parsing lib/mypy/typeshed/stdlib/3/_importlib_modulespec.pyi (_importlib_modulespec)
    LOG:  Loaded graph with 8 nodes
    LOG:  Found 2 SCCs; largest has 7 nodes
    LOG:  Processing SCC of size 7 (_importlib_modulespec mypy_extensions types abc typing sys builtins) as inherently stale
    LOG:  Processing SCC singleton (so_41869174) as inherently stale
    LOG:  No fresh SCCs left in queue
    LOG:  Build finished in 0.482 seconds with 8 modules, 1708 types, and 0 errors
    

    Because F().b is a bound method, it inherits the signature of the underlying function without the self argument (as it is the job of the bound method to pass in the bound instance).

    For example, the typing.get_type_hints() function, applied to the bound method, correctly omits self:

    >>> typing.get_type_hints(f.b)
    {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}