[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




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

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

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



Я знаю, что это было три года назад, но для тех, кто должен прийти к этому вопросу в будущем, для меня:

class_name.attribute 

работает просто отлично.







Вы можете использовать dir() в понимании списка, чтобы получить имена атрибутов:

names = [p for p in dir(myobj) if not p.startswith('_')]

Используйте getattr() для получения самих атрибутов:

attrs = [getattr(myobj, p) for p in dir(myobj) if not p.startswith('_')]



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

Вот как это работает в 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 , чтобы эмулировать тот же процесс поиска.




Links