Skip to content

Discrepancy in behavior of Callable instance fields #1113

Closed
@JelleZijlstra

Description

@JelleZijlstra

(Expanding from python/typeshed#7520 (comment))

Consider this code:

from typing import Callable

class X:
    f: Callable[[], int]
    g: Callable[["X"], int]

reveal_type(X().f())
reveal_type(X().g())

Here is how current type checkers handle it:

  • pyright complains about the second call (Expected 1 more positional argument)
  • pytype complains about the second call (Function <callable> expects 1 arg(s), got 0 [wrong-arg-count])
  • pyanalyze complains about the second call (Missing required positional argument: '__arg0' (code: incompatible_call))
  • pyre accepts both calls (I think there's a bug where it doesn't complain about missing arguments?)
  • mypy complains about the first one (main.py:8: error: Attribute function "f" with type "Callable[[], int]" does not accept self argument).

I feel like mypy is wrong here, because the behavior where self gets implicitly bound on instances is specific to functions, not all callables. But the type system sometimes conflates functions with callables, so I can see where mypy is coming from.

In either case, the discrepancy is unfortunate because it means we can't write typeshed stubs that satisfy both type checkers. We should come to an agreement on the right behavior and document it.

@Akuli pointed out a workaround for mypy's behavior: using a callable protocol (python/typeshed#7520 (comment))

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: otherOther topics not covered

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions