2

This list montre les méthodes dont vous avez besoin pour mettre en œuvre pour que votre classe soit "considérée" comme séquence: __getitem__, __len__, __contains__, __iter__, __reversed__, index et count. Pourquoi cette implémentation minimale ne fonctionne-t-elle pas, c'est-à-dire pourquoi issubclass(S, Sequence) is False?issubclass de classe de base abstraite Séquence

from collections import * 


class S(object): 
    def __getitem__(self, item): 
     raise IndexError 

    def __len__(self): 
     return 0 

    def __contains__(self, item): 
     return False 

    def __iter__(self): 
     return iter(()) 

    def __reversed__(self): 
     return self 

    def index(self, item): 
     raise IndexError 

    def count(self, item): 
     return 0 


issubclass(S, Iterable) # True :-) 
issubclass(S, Sized)  # True :-) 
issubclass(S, Container) # True :-) 
issubclass(S, Sequence) # False :-(

Existe-t-il une méthode supplémentaire que j'ai besoin d'implémenter? Ai-je mal compris les classes de base abstraites? Sous-classement Sequence rend issubclass retour True bien sûr, mais cela ne va pas à l'idée derrière abc, n'est-ce pas?

+0

Ce n'est pas parce qu'une classe implémente l'interface de séquence qu'elle en fait une sous-classe de Sequence. –

+2

Je pense que OP le sait déjà. Voir [abc] (https://docs.python.org/2/library/abc.html#module-abc). – Vlad

Répondre

4

Use the source, Luke!

Sequence ne met pas en œuvre son propre __subclasshook__, et toutes les implémentations de __subclasshook__ des parents de Sequence procéder à des contrôles comme celui-ci:

class Iterable: 
    ... 

    @classmethod 
    def __subclasshook__(cls, C): 
     if cls is Iterable: # <<<< 
      if _hasattr(C, "__iter__"): 
       return True 
     return NotImplemented 

Vous pouvez cependant explicitement register() votre classe en tant que Sequence :

Sequence.register(S) 

En ce qui concerne la raison pour laquelle Sequence n'implémente pas __subclasshook__, voir issue 16728 (quel titre était initialement "collections.abc.Sequence doit fournir __subclasshook__"). La question peut se résumer en disant qu'une séquence peut être beaucoup de choses, en fonction des besoins de ceux qui l'utilisent:

De nombreux algorithmes qui nécessitent une séquence seulement besoin __len__ et __getitem__. [...] collections.abc.Sequence est une interface beaucoup plus riche.

+0

En d'autres termes collections.Sequence est inutile (/ incomplet) sauf si utilisé comme un mixin? – kay

+0

@Kay: il vous donne les caractéristiques de nombreuses autres classes de base abstraites: vous obtenez une exception si vous essayez d'hériter sans définir toutes les méthodes requises, et vous pouvez explicitement 'register()' sous-classes arbitraires –

+0

Hm, semble flagrant surveillance par les pirates de Python à mon honnête. Connaissez-vous une raison pour laquelle 'Sequence .__ subclasshook__' n'est pas implémenté? – kay