2009-06-04 48 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