2009-06-04 49 views
4

我試圖實現infer_class函數,給定一個方法,計算出該方法所屬的類。如何推斷@staticmethod屬於的類?

到目前爲止,我有這樣的事情:

import inspect 

def infer_class(f): 
    if inspect.ismethod(f): 
     return f.im_self if f.im_class == type else f.im_class 
    # elif ... what about staticmethod-s? 
    else: 
     raise TypeError("Can't infer the class of %r" % f) 

它不爲@靜態方法的工作,因爲我無法想出一個辦法來實現這一目標。

有什麼建議嗎?

這裏是在行動infer_class

>>> class Wolf(object): 
...  @classmethod 
...  def huff(cls, a, b, c): 
...   pass 
...  def snarl(self): 
...   pass 
...  @staticmethod 
...  def puff(k,l, m): 
...   pass 
... 
>>> print infer_class(Wolf.huff) 
<class '__main__.Wolf'> 
>>> print infer_class(Wolf().huff) 
<class '__main__.Wolf'> 
>>> print infer_class(Wolf.snarl) 
<class '__main__.Wolf'> 
>>> print infer_class(Wolf().snarl) 
<class '__main__.Wolf'> 
>>> print infer_class(Wolf.puff) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 6, in infer_class 
TypeError: Can't infer the class of <function puff at ...> 
+1

你的源代碼,你可以讀父類。你爲什麼需要這個?你想達到什麼目的? – 2009-06-04 09:52:12

+2

假設我想編寫一個臨時存儲函數或方法的函數(爲了測試目的攔截調用或其他函數)。爲了做到這一點,我需要兩個成分:包含函數的對象和函數名,以便我可以執行`setattr(obj,func_name,my_stub)`。如果f是一個模塊級的函數,我使用`inspect.getmodule(f)`獲取對象和`f .__ name__`來獲取它的名字。對於類方法和實例方法,我使用上面的代碼。對於靜態方法,我看起來很失敗。 – 2009-06-04 17:45:57

回答

3

這是因爲staticmethods真的沒有方法。靜態方法描述符按原樣返回原始函數。沒有辦法獲得通過該函數訪問的類。但是,無論如何,沒有真正的理由使用staticmethods,總是使用classmethods。

我發現的靜態方法的唯一用途是將函數對象存儲爲類屬性,而不是將它們轉換爲方法。

+6

-1:「但是沒有任何真正的理由使用靜態方法,總是使用類方法。」你是指實例方法還是類方法?對於靜態方法有一些有效的用例,有時使用它們有「真正的原因」。 – nikow 2009-06-04 11:58:31

3

我有麻煩把自己居然建議這一點,但它似乎對簡單的情況下工作,至少:

import inspect 

def crack_staticmethod(sm): 
    """ 
    Returns (class, attribute name) for `sm` if `sm` is a 
    @staticmethod. 
    """ 
    mod = inspect.getmodule(sm) 
    for classname in dir(mod): 
     cls = getattr(mod, classname, None) 
     if cls is not None: 
      try: 
       ca = inspect.classify_class_attrs(cls) 
       for attribute in ca: 
        o = attribute.object 
        if isinstance(o, staticmethod) and getattr(cls, sm.__name__) == sm: 
         return (cls, sm.__name__) 
      except AttributeError: 
       pass