Python:如何检查对象的属性是否为方法?

3

我希望定义一个类,并使用__repr__方法,以只写出所有非方法属性的名称和值。我该如何做?我已经将其编写为以下形式,但我意识到这不检查属性类型。

class Example:
    def __repr__(self):
        return "\n".join(["%s: %s" % (x, getattr(self, x)) for x in dir(self) if not x.startswith('__')])

这里缺少对属性类型的检查。

你可以使用 inspect.ismethod 来判断属性是否为方法类型 :) - defactodeity
3个回答

5
你可以使用 "inspect" 来完成类似这样的操作:
from inspect import ismethod,getmembers

class Example:
    def __repr__(self):
        return "\n".join("%s: %s" % (k, v) for (k,v) in getmembers(self,lambda x: not ismethod(x)))

    def method(self):
        return 1

a = Example()
a.foo = 'bar'
print a

这也会捕获双下划线属性(__module____doc__)。如果您不想要它们,可以相当容易地将其过滤掉。

它将同时提取@property和类变量。 - kennytm
我认为它应该同时处理这两种情况,包括属性对象。毕竟,从API的角度来看,属性和属性没有区别...但是我想这真的取决于OP想要什么 :)。 - mgilson

2
假设你的类没有定义__slots__,你也可以直接迭代实例的__dict__(或通过vars()函数)来完成。
class Superclass:
    def __init__(self, w):
        self.w = w

class Example(Superclass):
    def __init__(self, x, y, z):
        super().__init__(1234)
        self.x = x
        self.y = y
        self.z = z

    @property
    def x_prop(self):
        return self.x

    @classmethod
    def do_something(cls, z):
        return str(cls) + str(z)

    def __call__(self):
        return 4444

    class_property = 42


    def __repr__(self):
        return "\n".join("%s: [%s]" % (k, v) for (k,v) in vars(self).items())

example = Example(2, lambda y: z, '4')
example2 = Example(example, 6j, b'90')

print(repr(example2))

这将打印

x: [x: [2]
y: [<function <lambda> at 0x7f9368b21ef0>]
z: [4]
w: [1234]]
y: [6j]
z: [b'90']
w: [1234]

2

2
这样做的缺点是你可以将可调用对象作为属性:例如 e = Example(); e.foo = lambda x:x*x - mgilson
更好的答案是 这个回答 ,针对 如何断言一个变量是实例方法? - Steven Rumbalski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接