[Python] Получение атрибутов класса


Answers

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

properties = props(MyClass)
Question

Я хочу получить атрибуты класса, скажем:

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

  def myfunc(self):
    return self.a

используя MyClass.__dict__ дает мне список атрибутов и функций и даже такие функции, как __module__ и __doc__ . Хотя MyClass().__dict__ дает мне пустой dict, если я явно не установил значение атрибута этого экземпляра.

Мне просто нужны атрибуты, в приведенном выше примере: a и b




Недавно мне нужно было найти что-то похожее на этот вопрос, поэтому я хотел бы опубликовать некоторую справочную информацию, которая может быть полезной для других, сталкивающихся с этим в будущем.

Вот как это работает в Python (от https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy ):

MyClass - объект класса, MyClass() - это экземпляр объекта класса. Экземпляр __dict__ экземпляра __dict__ только атрибуты и методы, специфичные для этого экземпляра (например, self.somethings ). Если атрибут или метод является частью класса, он находится в классе __dict__ . Когда вы выполняете MyClass().__dict__ , экземпляр MyClass создается без атрибутов или методов помимо атрибутов класса, таким образом, пустой __dict__

Поэтому, если вы скажете print(MyClass().b) , Python сначала проверяет файл MyClass().__dict__['b'] нового экземпляра и не находит b . Затем он проверяет класс MyClass.__dict__['b'] и находит b .

Вот почему вам нужен модуль inspect , чтобы эмулировать тот же процесс поиска.







Получить только атрибуты экземпляра легко.
Но получить атрибуты класса без функций немного сложнее.

Только атрибуты экземпляра

Если вам нужно только указать атрибуты экземпляра, просто используйте
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) использования
getattr ( 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

$ 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