获取类的属性

201 投票
21 回答
535906 浏览
提问于 2025-04-17 11:55

我想获取一个类的属性,比如说:

class MyClass():
  a = "12"
  b = "34"

  def myfunc(self):
    return self.a

使用 MyClass.__dict__ 可以让我看到这个类的所有属性和方法,甚至包括像 __module____doc__ 这样的特殊方法。而如果我用 MyClass().__dict__,得到的结果是一个空的字典,除非我特意给这个实例设置了属性值。

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

21 个回答

52

获取实例属性很简单。
但如果想要获取类属性而不包括函数,就有点复杂了。

仅获取实例属性

如果你只需要列出实例属性,只需使用
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) 的时候,应该改为
callable(getattr(MyClass, 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 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2

中的相同结果

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

这段代码是用来处理一些特定功能的。它可能涉及到一些数据的操作,或者是与用户交互的部分。具体来说,代码块中的内容会根据不同的输入来执行不同的任务。

在编程中,我们常常需要根据条件来决定要做什么,比如如果用户输入了某个值,就执行某个操作;如果输入了另一个值,就执行另一个操作。这种逻辑在代码中是非常常见的。

总之,这段代码的目的是为了让程序能够根据不同的情况做出相应的反应,帮助用户完成他们想要的事情。

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

properties = props(MyClass)
192

可以试试 inspect 模块。里面的 getmembers 和一些测试功能会很有帮助。

编辑:

举个例子,

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

……而更复杂的方法可能包括检查特殊属性的名字,甚至使用 metaclasses 哦;)

撰写回答