4
class A:
    def foo(self):
        print "foo()"

getattr(A, foo) # True
A.foo() # error

getattr(A(), foo) # True
A().foo() # prints "foo()"

话虽如此,这是我的问题:

我希望将测试用例元信息存储为测试用例类对象本身的属性,而不是它们的实例。
我有一个要提取的属性名称列表,但是如果有同名的实例方法,getattr(class_obj, attr)则将返回 True,但getattr(class_obj, attr)()会引发错误。

有没有办法告诉 getattr 不包含实例化类的属性而只包含类对象本身的属性?

编辑:我尝试class_obj.__dict__直接访问(我理解这是不好的做法),但它不包括一些属性,如__name__

编辑:改写问题。有没有办法区分 obj 类的方法和类实例的方法?

4

3 回答 3

4

这够好吗?

import types
class Test(object):
    @staticmethod
    def foo():
        print 'foo'

    def bar(self):
        print 'bar'

结合:

>>>(isinstance(getattr(Test, 'foo'), types.FunctionType),
    isinstance(getattr(Test, 'bar'), types.FunctionType))
True, False

您还可以使用该inspect模块:

>>> inspect.isfunction(Test.foo)
True
>>> inspect.isfunction(Test.bar)
False

通过一些额外的工作,您甚至可以将类方法与实例方法和静态方法区分开来:

import inspect

def get_type(cls, attr):
    try:
        return [a.kind for a in inspect.classify_class_attrs(cls) if a.name == attr][0]
    except IndexError:
        return None

class Test(object):
    @classmethod
    def foo(cls):
        print 'foo'

    def bar(self):
        print 'bar'

    @staticmethod
    def baz():
        print 'baz'

您可以将其用作:

>>> get_type(Test, 'foo')
'class method'
>>> get_type(Test, 'bar')
'method'
>>> get_type(Test, 'baz')
'static method'
>>> get_type(Test, 'nonexistant')
None
于 2013-08-28T21:29:10.657 回答
3

您的结果来自对 的错误定义foo,而不是类属性的任何基础语义。默认情况下,在类中声明的函数是实例方法,它必须至少接受一个参数,即类的实例。按照惯例,它被称为self

class A:
    def foo(self):
        print "foo()"

通常,您会像这样调用这样的方法:

a = A()
a.foo()    # passes the object 'a' implicitly as the value of the parameter 'self'

但这也是合法的

a = A()
A.foo(a)   # pass the object 'a' explicitly as the value of the parameter 'self'

为了在不接受任何此类隐式参数的类中定义一个函数,您需要使用装饰器对其进行@staticmethod装饰:

class A:
    @staticmethod
    def foo():
        print "foo()"

现在,您可以调用foo您之前尝试的方式:

>>> A.foo()
foo()
于 2013-08-28T21:32:37.607 回答
0

你想要这样的东西:

from inspect import ismethod
from collections import Callable
def can_i_call(func):
    if not isinstance(func, Callable):
        # not a callable at all
        return False

    if not ismethod(func):
        # regular function or class or whatever
        return True

    # func is a method
    return func.im_self is not None

注意:这只会测试调用尝试是否会出错,因为您正在调用没有self. 它不保证func()一定会成功,即不会因任何其他原因而失败。

于 2013-08-28T21:35:15.143 回答