【问题标题】:Determine if given class attribute is a property or not, Python object确定给定的类属性是否为属性,Python 对象
【发布时间】:2013-07-18 23:11:09
【问题描述】:

这一切都在标题中。下面是一个例子:

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)

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

【问题讨论】:

    标签: python


    【解决方案1】:

    您需要查看类(通常是描述符的情况),对于您可以通过 __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
    

    【讨论】:

    • 这并没有回答 OP 如何将其集成到他们的循环中以测试每个属性,只回答如何测试特定的、已知名称的属性。
    【解决方案2】:

    我曾经问过一个类似的问题。当然,您会遇到的麻烦是,如果不调用 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__() 属性。但是这种方法的问题是所有函数和方法本身都是描述符,因此会被该检查捕获。试图找出所有异常很快就会变得很愚蠢。

    【讨论】:

      【解决方案3】:

      要添加到 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
      

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • 我花了大约 30 分钟来寻找我的问题的答案......简单的单线,正是我需要的。谢谢。
        猜你喜欢
        • 2013-07-30
        • 1970-01-01
        • 2014-10-12
        • 1970-01-01
        • 1970-01-01
        • 2015-02-19
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        相关资源
        最近更新 更多