2016-01-17 13 views
12

Il nuovo modulo typing contiene diversi oggetti con nomi come "SupportsInt" (-Float, -Bytes, ecc.). Il nome e le descrizioni su the documentation page for the module potrebbero essere letti per suggerire che è possibile verificare se un oggetto è di un tipo che "supporta __int__()". Ma se si tenta di utilizzare isinstance(), dà una risposta che rende chiaro che questo non è qualcosa che sono destinati a fare:"I protocolli non possono essere usati con isinstance()" - perché no?

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

D'altra parte, è possibile utilizzare issubclass():

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

Che cos'è un "protocollo" in questo contesto? Perché non consente l'utilizzo di isinstance() in questo modo?

+1

Lo scopo del modulo 'typing' è ** non ** fornire un modo per eseguire tali controlli. Ha lo scopo di fornire un modo comune per fornire i tipi di funzioni ecc. Nelle loro annotazioni. La duck tipizzazione è ancora preferita, puoi usare questi tipi per dire al tuo utente come si intende chiamare la funzione. – Bakuriu

+0

@Bakuriu, ma il modulo di battitura è fornito in parte per consentire il controllo statico dei tipi, e quindi è ragionevole supporre che fornirà il meccanismo per identificare (dire) se un particolare oggetto è di un tipo particolare. Se invoco una funzione che passa 5 come parametro annotato come di tipo typing.SupportsInt, allora come farà un correttore di tipo statico a sapere che questo è valido? – Hammerite

risposta

1

Questo è tutto del ragionamento data in PEP 484, il PEP per il modulo typing:

Perché typing.Callable fa doppio dovere come sostituzione per collections.abc.Callable, isinstance (x, typing.Callable) è implementato differendo a `isinstance (x, collections.abc.Callable). Tuttavia, isinstance (x, typing.Callable [...]) non è supportato.

Un protocollo è anche noto come magic method. Questi sono la maggior parte dei protocolli di Python (elenco completo here):

>>> 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__'] 

non ho trovato alcuna ragione chiara del motivo per cui typing non supporta isinstance. La ragione per cui issubclass funziona è che isinstance utilizza il protocollo __class_ che non è consentito in typing, mentre issubclass utilizza il protocollo __subclasshook__ consentito. Credo che la ragione sia che la funzionalità era già codificata in collections.abc.Callable e non volevano ricodificarla nel modulo typing.

Problemi correlati