2017-07-26 4 views
1

J'ai regardé un screencast de David Beazly dans lequel il impléménait la vérification de type en utilisant plusieurs ou plus spécifiquement l'héritage du diamant. Je pensais que son approche avait l'air vraiment cool, mais cela m'a aussi troublé et je n'arrive tout simplement pas à comprendre comment ça fonctionne. Voici le code im parle:Comprendre l'héritage multiple et super basé sur du code de David Beazly

class Contract: 
    @classmethod 
    def check(cls, value): 
     pass 


class Integer(Contract): 
    @classmethod 
    def check(cls, value): 
     assert isinstance(value, int), 'Expected int' 
     super().check(value) 


class Positive(Contract): 
    @classmethod 
    def check(cls, value): 
     assert value > 0, 'Must be > 0' 
     super().check(value) 


class PositiveInteger(Positive, Integer): 
    pass 

Et ici, il est en action:

>>> PositiveInteger.check(-3) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in check 
AssertionError: Must be > 0 
>>> PositiveInteger.check(4.88) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in check 
    File "<stdin>", line 4, in check 
AssertionError: Expected int 

Mes questions sont les suivantes:

  1. Pourquoi la définition d'une classe de base contrat avec une vérification de méthode nécessaire pour que cela fonctionne?

  2. J'ai une compréhension de base de ce que fait super. Je sais que cela nous permet d'éviter d'appeler explicitement la classe de base et de traiter en quelque sorte de l'héritage multiple. Mais que fait-il dans cet exemple exactement?

+0

Relié, sinon dupliqué: [Comment super Python fonctionne-t-il avec plusieurs héritages?] (Https://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance –

+0

@NickT: Je suis conscient de ce sujet et je l'ai lu mais cela ne m'a pas aidé à comprendre ce problème – f1nan

+0

Je pense que l'idée est que quelque part dans le MRO il doit/doit y avoir une méthode donc vous le mettez dans le classe de base - même si elle ne fait rien ou déclenche simplement une exception NotImplemented. – wwii

Répondre

1

Passons en revue ligne par ligne comme un débogueur.

PositiveInteger.check(x) 

# Method resolution order: 
# PositiveInteger, Positive, Integer, Contract (from Positive), Contract (from Integer) 

# Look through MRO for .check() method. Found in Positive. 

assert x > 0 
super().check(value) 

# super() checks for next .check() method in MRO. Found in Integer 

assert isinstance(x, int) 
super().check(value) 

# super() checks for next .check() method in MRO. Found in Contract 

pass 

Pour trouver facilement l'ordre de résolution de la méthode, utilisez inspect.getmro().

Si vous aviez explicitement utilisé la classe de base, après Positive, la classe de base est Contract, donc Integer ne serait jamais appelée.

Vous devez définir .check() dans Contract que lorsque vous appelez le dernier super(), si Contract n'a pas eu la méthode .check(), il aurait soulevé un AttributeError, comme super() n'aurait pas pu le trouver.