44

这一切都在标题中。这是以下示例:

class A(object):
    my_var = 5

    def my_method(self, drink='beer'):
        return 'I like %s' % drink

    @property
    def my_property(self):
        return 'I do not drink coffee'

我实例化了一个 A 对象,我想知道每个属性的类型以及它是否是可调用的。为此,我正在使用dir().

obj = A()

for attr in dir(obj):
    print 'Type: %s' % type(obj)
    print 'Is callable: %s' % callable(attr)

我还必须知道属性是否是属性。我确信有办法知道这一点。所有建议将不胜感激。

4

4 回答 4

39

您需要查看类(通常是描述符的情况),对于您可以通过__class__属性或使用 type 函数找到的对象:

>>> obj.__class__.my_property
<property object at 0xb74bd16c>

或通过

>>> type(obj).my_property
<property object at 0xb720b93c>

这些会产生相同的“属性对象”,就好像您要直接检查类的属性一样(这意味着您知道代码中的类的名称,而不是像您可能应该做的那样动态检查它):

>>> A.my_property
<property object at 0xb7312345>

因此,要测试对象的特定属性是否是属性,这将是一种解决方案:

>>> isinstance(type(obj).my_property, property)
True
于 2013-07-18T23:28:56.053 回答
27

我曾经问过一个类似的问题。当然,您会遇到的麻烦是,如果不调用 getter,就无法通过实例访问属性以确定其类型,这会为您获取 getter 返回的任何类型。因此,您必须通过其类而不是通过实例来访问该属性。

property已经是一种类型,因此您可以直接与之比较。(我最初在这里有一些多余的代码,可以从具有属性的类中获取属性类型。我认为这是必要的,因为我在测试时出现了拼写错误。)

obj_type = type(obj)

for attr in dir(obj):
    if isinstance(getattr(type(obj), attr, None), property):
        print attr, "is a property"

不要担心有一个同名的实例属性。如果类上有同名的数据描述符(property是数据描述符),则在属性查找中将忽略它。

当然,任何类都可以是数据描述符,而不仅仅是property,所以理论上你真的想检查类型的__get__()和/或__set__()和/或__delete__() 属性。但是这种方法的问题是所有函数和方法本身都是描述符,因此会被该检查捕获。试图找出所有的例外情况很快就会变得愚蠢。

于 2013-07-18T23:28:10.183 回答
2

为了综合以前的答案,这里有一个方便的函数,它返回类属性的名称。

def get_properties_names(cls):
    return [k for k, v in vars(cls).items() if isinstance(v, property)]

因此,如果您想要对象的属性obj,请使用:

props = get_properties_names(type(obj))
于 2021-01-20T13:01:28.810 回答
2

要添加到 John La Rooy 的答案(和 bugmenot123 的评论),很容易扩展代码以检查任意属性名称。


让我们定义一个具有属性的类及其实例:

class MyClass:
    not_a_property = None
    @property
    def my_property(self):
            pass
    def my_method(self):
            pass

my_object = MyClass()

我们可以简单地使用getattr带有任意字符串的 any 来检查给定对象的类的属性是否是属性,就像 John La Rooy 演示的那样:

>>> isinstance(getattr(type(my_object), 'not_a_property'), property)
False
>>> isinstance(getattr(type(my_object), 'my_property'), property)
True
>>> isinstance(getattr(type(my_object), 'my_method'), property)
False

要获取对象的所有属性方法名称,您可以循环遍历dir该类,如下所示:

for attr in dir(type(my_object)):
    print(
            f'{attr} is a property method:'.ljust(42),
            isinstance(getattr(type(my_object), attr), property)
    )

上面的循环打印以下输出:

__class__ is a property method:            False
__delattr__ is a property method:          False
__dict__ is a property method:             False
__dir__ is a property method:              False
__doc__ is a property method:              False
__eq__ is a property method:               False
__format__ is a property method:           False
__ge__ is a property method:               False
__getattribute__ is a property method:     False
__gt__ is a property method:               False
__hash__ is a property method:             False
__init__ is a property method:             False
__init_subclass__ is a property method:    False
__le__ is a property method:               False
__lt__ is a property method:               False
__module__ is a property method:           False
__ne__ is a property method:               False
__new__ is a property method:              False
__reduce__ is a property method:           False
__reduce_ex__ is a property method:        False
__repr__ is a property method:             False
__setattr__ is a property method:          False
__sizeof__ is a property method:           False
__str__ is a property method:              False
__subclasshook__ is a property method:     False
__weakref__ is a property method:          False
my_method is a property method:            False
my_property is a property method:          True
not_a_property is a property method:       False
于 2020-04-16T16:21:54.740 回答