Подтвердить что ты не робот

"Протоколы нельзя использовать с isinstance()" - почему бы и нет?

Новый typing модуль содержит несколько объектов с именами типа "SupportsInt" (-Float, -Bytes и т.д.). Имя и описания страницы документации для модуля можно прочитать, чтобы предложить проверить, является ли объект типом, который поддерживает __int__() ". Но если вы попытаетесь использовать isinstance(), он даст ответ, который даст понять, что это не то, что вы должны делать:

>>> isinstance(5, typing.SupportsInt)
(Traceback omitted)
TypeError: Protocols cannot be used with isinstance().

С другой стороны, вы можете использовать issubclass():

>>> issubclass((5).__class__, typing.SupportsInt)
True
>>> issubclass(type(5), typing.SupportsInt)
True

Что такое "протокол" в этом контексте? Почему это запрещает использование isinstance() таким образом?

4b9b3361

Ответ 1

Это все рассуждения, приведенные в PEP 484, PEP для модуля typing:

Потому что typing.Callable выполняет двойную работу в качестве замены для коллекций .abc.Callable, isinstance (x, typing.Callable) реализуется путем переноса на `isinstance (x, collections.abc.Callable). Однако isinstance (x, typing.Callable [...]) не поддерживается.

Протокол также известен как magic method. Это большинство протоколов python (полный список здесь):

>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', 
'__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__']

Я не нашел ясной причины, почему typing не поддерживает isinstance. Причина, по которой работает issubclass, заключается в том, что isinstance использует протокол __class_, который не разрешен в typing, а issubclass использует протокол __subclasshook__, который разрешен. Я считаю, что причина в том, что функциональность уже была закодирована в collections.abc.Callable, и они не хотели перекодировать ее в модуле typing.