2009-06-07 81 views
52

如何獲得在Python中定義方法的類?獲取定義方法的類

我想下面的例子打印「__main__.FooClass」:

class FooClass: 
    def foo_method(self): 
     print "foo" 

class BarClass(FooClass): 
    pass 

bar = BarClass() 
print get_class_that_defined_method(bar.foo_method) 
+0

您使用的是什麼版本的Python? 在2.2之前,你可以使用im_class,但是這已經改變,以顯示綁定的自我對象的類型。 – 2009-06-07 02:40:18

+1

很高興知道。但我使用2.6。 – 2009-06-07 02:48:10

回答

54
import inspect 

def get_class_that_defined_method(meth): 
    for cls in inspect.getmro(meth.im_class): 
     if meth.__name__ in cls.__dict__: 
      return cls 
    return None 
+0

它的工作原理,謝謝! – 2009-06-07 02:29:24

5

感謝Sr2222您指出我錯過了點...

這裏的修正方法是就像Alex的,但不需要導入任何東西。但我認爲這不是一個好轉,除非有一個龐大的繼承類的層次結構,因爲一旦找到定義的類,此方法就會停止,而不是像getmro那樣返回整個繼承。如上所述,這是一個不太可能發生的情況。

def get_class_that_defined_method(method): 
    method_name = method.__name__ 
    if method.__self__:  
     classes = [method.__self__.__class__] 
    else: 
     #unbound method 
     classes = [method.im_class] 
    while classes: 
     c = classes.pop() 
     if method_name in c.__dict__: 
      return c 
     else: 
      classes = list(c.__bases__) + classes 
    return None 

和示例:

>>> class A(object): 
...  def test(self): pass 
>>> class B(A): pass 
>>> class C(B): pass 
>>> class D(A): 
...  def test(self): print 1 
>>> class E(D,C): pass 

>>> get_class_that_defined_method(A().test) 
<class '__main__.A'> 
>>> get_class_that_defined_method(A.test) 
<class '__main__.A'> 
>>> get_class_that_defined_method(B.test) 
<class '__main__.A'> 
>>> get_class_that_defined_method(C.test) 
<class '__main__.A'> 
>>> get_class_that_defined_method(D.test) 
<class '__main__.D'> 
>>> get_class_that_defined_method(E().test) 
<class '__main__.D'> 
>>> get_class_that_defined_method(E.test) 
<class '__main__.D'> 
>>> E().test() 
1 

亞歷溶液返回相同的結果。只要Alex方法可以使用,我會用它來代替這個。

1

我開始做一些有點類似的事情,基本上這個想法是檢查基類中的某個方法是否已經實現或者不在子類中。原來我做這件事的方式,我無法檢測到中級班實際上正在實施該方法。

我的解決方法其實很簡單;設置方法屬性並稍後測試其存在。下面是整個事情的簡化:

class A(): 
    def method(self): 
     pass 
    method._orig = None # This attribute will be gone once the method is implemented 

    def run_method(self, *args, **kwargs): 
     if hasattr(self.method, '_orig'): 
      raise Exception('method not implemented') 
     self.method(*args, **kwargs) 

class B(A): 
    pass 

class C(B): 
    def method(self): 
     pass 

class D(C): 
    pass 

B().run_method() # ==> Raises Exception: method not implemented 
C().run_method() # OK 
D().run_method() # OK 

UPDATE:其實叫從run_method()method()(是不是精神?),並把它傳遞給未修改方法的所有參數。

P.S .:此答案不直接回答問題。恕我直言,人們有兩個理由想知道哪個類定義了一種方法;首先是在調試代碼中指向一個類(例如在異常處理中),其次是確定該方法是否已被重新實現(其中方法是要由程序員實現的存根)。這個答案以不同的方式解決了第二種情況。

2

我不知道爲什麼從來沒有人提出這爲什麼頂端回答有50個upvotes當它是緩慢的地獄,但你也可以做到以下幾點:

def get_class_that_defined_method(meth): 
    return meth.im_class.__name__ 

爲Python 3我相信這改變了,你需要看看.__qualname__

相關問題