2017-07-26 6 views
1

David Beazlyが複数のまたはより具体的なダイヤモンド継承を使用して型チェックを実装しているのを見たのですが、screencastを見ました。私は彼のアプローチが本当にクールだと思ったが、それはまた私を混乱させ、私は単にそれがどのように働いているのか分かりません。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 

そして、ここではアクションである:ここでの話コードイムはある

>>> 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 

は、私の質問は以下のとおりです。

  1. なぜと基底クラスの契約の定義がありますこの作業を行うために必要なメソッドチェック?

  2. 私はスーパーのことを基本的に理解しています。私は、基本クラスを明示的に呼び出すことを避け、何らかの形で複数の継承を扱うことができることを知っています。しかし、この例ではどういうことがありますか?

+0

関連する場合、重複しない場合:[Pythonのsuper()は多重継承でどのように動作しますか?](https://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance ) –

+0

@NickT:私はこのスレッドを認識していますが、それを読んだのですが、この問題を理解する助けにはなりませんでした。 – f1nan

+0

私は、MROのどこかにメソッドがあるはずです基本クラス - 何もしないか、NotImplemented例外が発生しただけであっても。 – wwii

答えて

1

デバッガのように行単位で処理してみましょう。

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 

簡単に解決方法の順序を見つけるには、inspect.getmro()を使用します。

Positiveの後に明示的に基本クラスを使用した場合、基本クラスはContractであるため、Integerは決して呼び出されません。 super()がそれを見つけることができなかっただろうと

あなたはContract.check()メソッドを持っていなかった場合は、最後のsuper()を呼び出すときのようContract.check()を定義する必要があり、それは、AttributeErrorを提起しているだろう。

関連する問題