确定给定的类属性是否是属性,Python对象

时间:2013-07-18 23:11:09

标签: python

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

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 个答案:

答案 0 :(得分:22)

我曾经问过类似的问题。当然,您遇到的麻烦是,您无法通过实例访问属性以确定其类型而无需调用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__()和/或{{1类型上的属性。但是这种方法的问题在于所有函数和方法本身都是描述符,因此会被检查所捕获。试图找到所有例外很快就变得愚蠢。

答案 1 :(得分:20)

您需要查看该类(一般情况下是描述符的情况),对于您可以通过 attribut或使用类型函数找到的对象:

>>> 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

答案 2 :(得分:1)

要添加到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来检查给定对象的类的属性是否是属性,就像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

答案 3 :(得分:0)

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

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))