2017-07-26 79 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. 我對super有什麼基本的理解。我知道它可以讓我們避免明確調用基類,並以某種方式處理多重繼承。但是這個例子究竟做了什麼?

+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

您需要Contract定義.check()當你調用最後super(),如果Contract沒有足夠的.check()方法,它會引發AttributeError,作爲super()不會已經能夠找到它。