获取一个类的属性

我想获得一个类的属性,说:

class MyClass(): a = "12" b = "34" def myfunc(self): return self.a 

使用MyClass.__dict__给了我一个属性和函数的列表,甚至像__module____doc__这样的函数。 虽然MyClass().__dict__给我一个空的字典,除非我明确设置该实例的属性值。

我只是想要的属性,在上面的例子是: ab

尝试检查模块。 getmembers和各种testing应该是有帮助的。

编辑:

例如,

 class MyClass(object): a = '12' b = '34' def myfunc(self): return self.a >>> import inspect >>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a))) [('__class__', type), ('__dict__', <dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>, '__doc__': None, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 'a': '34', 'b': '12', 'myfunc': <function __main__.myfunc>}>), ('__doc__', None), ('__module__', '__main__'), ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>), ('a', '34'), ('b', '12')] 

现在,这些特殊的方法和属性会让我神经紧张 – 这些方法可以通过多种方式处理,其中最简单的方法就是根据名称进行过滤。

 >>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a))) >>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))] [('a', '34'), ('b', '12')] 

…其中更复杂的可以包括特殊的属性名称检查甚至元类;)

 def props(cls): return [i for i in cls.__dict__.keys() if i[:1] != '_'] properties = props(MyClass) 

myfunc MyClass一个属性。 这就是运行时发现的:

 myinstance = MyClass() myinstance.myfunc() 

它在myinstance上查找一个名为myfunc的属性,找不到它,看到myinstanceMyClass一个实例并在那里查找它。

所以MyClass完整属性列表是:

 >>> dir(MyClass) ['__doc__', '__module__', 'a', 'b', 'myfunc'] 

(请注意,我正在使用dir作为列出类的成员的简单方法:只能以探索性方式使用,而不能用于生产代码)

如果你只想要特定的属性,你需要使用一些标准来过滤这个列表,因为__module____module__myfunc在任何方面都不是特殊的,它们的属性和bb属性完全一样。

我从来没有使用Matt和Borealid提到的inspect模块,但是从一个简单的链接看起来它有testing来帮助你这样做,但是你需要编写你自己的谓词函数,因为它看起来是你想要的大致是那些不通过isroutinetesting的属性, 不能以两个下划线开始和结束。

另请注意:通过使用class MyClass():在Python 2.7中,您正在使用过时的旧式类。 除非你故意这么做,否则你应该把类定义为class MyClass(object): 。 在Python 3中没有“旧式”类,这种行为是默认的。 但是,使用newstyle类会为您带来更多自动定义的属性:

 >>> class MyClass(object): a = "12" b = "34" def myfunc(self): return self.a >>> dir(MyClass) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'myfunc'] 

MyClass().__class__.__dict__

然而,“正确的”是通过检查模块来做到这一点。

我的解决scheme来获得一个类的所有属性(而不是方法)

 def get_class_attrs(cls): return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__']) 

我最近需要找出类似于这个问题的东西,所以我想发布一些背景信息,可能会有助于未来面临相同的其他人。

以下是它在Python中的工作原理(从https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy ):

MyClass是一个类对象, MyClass()是类对象的一个​​实例。 一个实例的__dict__只包含特定于该实例的属性和方法(例如self.somethings )。 如果一个属性或者方法是一个类的一部分,它就在这个类的__dict__ 。 当你做MyClass().__dict__MyClass一个实例被创build,除了类属性之外没有任何属性或方法,因此空的__dict__

所以,如果你说print(MyClass().b) ,Python首先检查新实例的字典MyClass().__dict__['b']并找不到b 。 然后检查类MyClass.__dict__['b']并findb

这就是为什么您需要inspect模块来模拟相同的search过程。

 import re class MyClass: a = "12" b = "34" def myfunc(self): return self.a attributes = [a for a, v in MyClass.__dict__.items() if not re.match('<function.*?>', str(v)) and not (a.startswith('__') and a.endswith('__'))] 

对于MyClass的一个实例,比如

 mc = MyClass() 

在列表理解中使用type(mc)来代替MyClass 。 但是,如果dynamic地向mc添加一个属性,例如mc.c = "42" ,则在此策略中使用type(mc)时,该属性不会显示出来。 它只给出了原始类的属性。

为了获得一个类实例的完整字典,你需要结合type(mc).__dict__mc.__dict__ type(mc).__dict__的字典。

 mc = MyClass() mc.c = "42" # Python 3.5 combined_dict = {**type(mc).__dict__, **mc.__dict__} # Or Python < 3.5 def dict_union(d1, d2): z = d1.copy() z.update(d2) return z combined_dict = dict_union(type(mc).__dict__, mc.__dict__) attributes = [a for a, v in combined_dict.items() if not re.match('<function.*?>', str(v)) and not (a.startswith('__') and a.endswith('__'))] 

只获取实例属性很容易。
但是如果没有这个函数,也要获得这个类的属性会有点棘手。

仅实例属性

如果你只需要列出实例属性就可以使用
for attribute, value in my_instance __dict__ items()

 >>> from __future__ import (absolute_import, division, print_function) >>> class MyClass(object): ... def __init__(self): ... self.a = 2 ... self.b = 3 ... def print_instance_attributes(self): ... for attribute, value in self.__dict__.items(): ... print(attribute, '=', value) ... >>> my_instance = MyClass() >>> my_instance.print_instance_attributes() a = 2 b = 3 >>> for attribute, value in my_instance.__dict__.items(): ... print(attribute, '=', value) ... a = 2 b = 3 

实例和类属性

为了得到没有函数的类属性 ,诀窍是使用callable()

但是静态方法 并不总是可以被callable

因此,而不是使用callable(value)使用
callablegetattrMyClass, attribute))

 from __future__ import (absolute_import, division, print_function) class MyClass(object): a = "12" b = "34" # class attributes def __init__(self, c, d): self.c = c self.d = d # instance attributes @staticmethod def mystatic(): # static method return MyClass.b def myfunc(self): # non-static method return self.a def print_instance_attributes(self): print('[instance attributes]') for attribute, value in self.__dict__.items(): print(attribute, '=', value) def print_class_attributes(self): print('[class attributes]') for attribute in MyClass.__dict__.keys(): if attribute[:2] != '__': value = getattr(MyClass, attribute) if not callable(value): print(attribute, '=', value) v = MyClass(4,2) v.print_class_attributes() v.print_instance_attributes() 

注意: print_class_attributes()应该是@staticmethod
但不是在这个愚蠢和简单的例子。

结果为python2

 $ python2 ./print_attributes.py [class attributes] a = 12 b = 34 [instance attributes] c = 4 d = 2 

python3的结果相同

 $ python3 ./print_attributes.py [class attributes] b = 34 a = 12 [instance attributes] c = 4 d = 2 

我知道这是三年前的事,但对于未来这个问题的人来说,对我来说,

 class_name.attribute 

工作得很好。