这一切都在标题中。以下是以下示例:
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)
我还必须知道属性是否属性。我确信有办法知道这一点。 所有建议将不胜感激。
答案 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))