Struggling to understand Callable type hinting
Ian Pilcher
arequipeno at gmail.com
Sat Jan 18 09:52:02 EST 2025
(Note: I have mail delivery disabled for this list and read it through
GMane, so I am unable to respond with correct threading if I'm not cc'ed
directly.)
On 1/17/25 7:26 PM, dn via Python-list wrote:
> On 18/01/25 12:33, Ian Pilcher via Python-list wrote:
>> I am making my first attempt to use type hinting in a new project, and
>> I'm quickly hitting areas that I'm having trouble understanding. One of
>> them is how to write type hints for a method decorator.
>>
>> Here is an example that illustrates my confusion. (Sorry for the
>> length.)
>>
>>
>> import collections.abc
>>
>> class BufferScanner(object):
>>
> ...
>
>> @staticmethod
>> def _check_eof(method: collections.abc.Callable -> (
>> collections.abc.Callable
>> ):
> ...
>>
>> I cannot figure out how to correctly specify the Callable argument and
>> return type for _check_eof(). As indicated by the name, method should
>> be a method (of the BufferScanner class), so its first positional
>> argument should always be an instance of BufferScanner, but it could
>> have any combination of positional and/or keyword arguments after that.
>
> Is it a typing problem?
> The def is not syntactically-correct (parentheses).
Yes, but only when I re-typed it in my email client to avoid word-
wrapping issues.
> What happens once corrected?
Once the missing parenthesis is added, the version in my original post
works just fine, but it's incomplete, because the Callables aren't
parameterized.
Based on what I've read, I would expect to be able to replace:
@staticmethod
def _check_eof(method: collections.abc.Callable) -> (
collections.abc.Callable
):
...
with something like this:
@staticmethod
def _check_eof(
method: collections.abc.Callable[[BufferScanner, ...], None]
) -> (
collections.abc.Callable[[BufferScanner, ...], bool]
):
...
But Mypy gives me a bunch of errors when I do that.
bs.py:19: error: Unexpected "..." [misc]
bs.py:21: error: Unexpected "..." [misc]
bs.py:32: error: Argument 1 to "_check_eof" of "BufferScanner" has
incompatible type "Callable[[BufferScanner], None]"; expected
"Callable[[BufferScanner, Any], None]" [arg-type]
Found 3 errors in 1 file (checked 1 source file)
(And even that wouldn't really be correct, if it worked, because it
doesn't express the fact that the arguments of the two Callables are the
same. I believe that ParamSpecs are supposed to address this, but there
doesn't seem to be any way to use a ParamSpec when one or more of the
parameter types is known.
> Also, which tool is 'complaining', and what does it have to say?
Mypy 1.14.1.
> General comment: as far as type-hints go, rather than trying to learn
> how to deal with complex situations, it might be better to ease-in
> gradually - add the easy stuff now, and come back to deal with the rest
> later (otherwise the typing 'tail' is wagging the coding 'dog'!)
Makes sense ... except that this decorator is what motivated me to use
type hinting in this project in the first place.
--
========================================================================
If your user interface is intuitive in retrospect ... it isn't intuitive
========================================================================
More information about the Python-list
mailing list