2013-09-05 97 views
0

Cooperative methods and superGuido在python中實現Super時出現了什麼問題?

這是一個例子純Python實現的內置super由Guido用於說明目的。我需要在類別Super下執行一些說明

在下面的代碼調用someobj.__mro__將不起作用。看到我的評論反對該行。 隨着內置super只是一個錯誤拋出。

TypeError: super(type, obj): obj must be an instance or subtype of type

問:

我的問題是什麼是有擺在首位該行的意圖是什麼?

因此,如果傳入的對象不是傳入的類中的實例,那麼請使用該對象的mro ...爲什麼?

class Super(object): 
     def __init__(self, type, obj=None): 
      self.__type__ = type 
      self.__obj__ = obj 
     def __get__(self, obj, type=None): 
      if self.__obj__ is None and obj is not None: 
       return Super(self.__type__, obj) 
      else: 
       return self 
     def __getattr__(self, attr): 
      if isinstance(self.__obj__, self.__type__): 
       starttype = self.__obj__.__class__ 
      else: 
       starttype = self.__obj__ ## This line does not work 
      mro = iter(starttype.__mro__) 
      for cls in mro: 
       if cls is self.__type__: 
        break 
      # Note: mro is an iterator, so the second loop 
      # picks up where the first one left off! 
      for cls in mro: 
       if attr in cls.__dict__: 
        x = cls.__dict__[attr] 
        if hasattr(x, "__get__"): 
         x = x.__get__(self.__obj__) 
        return x 
      raise AttributeError, attr 

class A(object): 
     def m(self): 
      ''' m in A''' 
      return "A" 

class B(A): 
     def m(self): 
      ''' m in B''' 
      return "B" + Super(B, self).m() 

class C(A): 
     def m(self): 
      ''' m in C ''' 
      return "C" + Super(C, self).m() 

class D(C): 
     def m(self): 
      ''' m in D''' 
      return "D" + Super(B, self).m() 

print D().m() # "DCBA" 

堆棧跟蹤:

Traceback (most recent call last): 
    File "./supertest.py", line 73, in <module> 
    print D().m() # "DCBA" 
    File "./supertest.py", line 71, in m 
    return "D" + Super(B, self).m() 
    File "./supertest.py", line 33, in __getattr__ 
    mro = iter(starttype.__mro__) 
AttributeError: 'D' object has no attribute '__mro__' 
+0

發佈整個堆棧跟蹤。 – Marcin

回答

6

TypeError: super(type, obj): obj must be an instance or subtype of type

你通過爲 obj是一個老式的對象(舊式類的實例)的對象。這些全都具有類型 classobj並且不是 object的子類,並且不是 type(或 type的子類)。

儘管在老式對象的描述中,被刪除的文本是正確的,但是看到了完整的代碼和異常,這不是導致該異常的問題。上面的例外是內置super捕捉到以下錯誤:D不是B的子類,所以super告訴你它不能對這對輸入做任何事情。

我的問題是,首先有這條線的意圖是什麼?

觸發您的回溯問題(完整的回溯,而不是第一個錯誤,處理上面)是D不是B一個子類。

在此代碼:

if isinstance(self.__obj__, self.__type__): 
    starttype = self.__obj__.__class__ 
else: 
    starttype = self.__obj__ ## This line does not work 
mro = iter(starttype.__mro__) 

的假設是,如果__obj__不是__type__一個實例,然後__obj__是一種類型本身,以及它有一個MRO。對於您提供的類型不是__obj__的基類(或類)的情況,沒有任何處理程序,因爲沒有什麼super(或Super)可以對其進行明智的處理。

這裏唯一的設計缺陷是構造函數應該可以捕獲這種情況,並生成適當的異常。

最後,我注意到您發佈的代碼與鏈接到的文檔中的代碼不同。 Guido的代碼實際上並沒有觸發這個問題。

+0

@abc在發佈完整的堆棧跟蹤之前,我無法對您的代碼發表評論。你所說的只是一條線「不起作用」。 – Marcin

+0

好吧,我現在發佈了堆棧跟蹤。但你真的需要仔細看看我在問什麼。請不要專注於代碼中的錯誤。 – abc

+0

@abc'Super'代碼沒有錯誤。正如我在上面解釋的那樣,這個錯誤就在你的使用中。 – Marcin

0

我明白了。內建super可以這樣調用:super(type, type2)它要求type2是類型的子類。在Super執行時,如此調用Super(type, type2)isinstance(type2, type)將會失敗,導致mro正在評估類型2。所以基本上超級試圖與內建功能相同

相關問題