Подтвердить что ты не робот

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

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

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

  def myfunc(self):
    return self.a

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

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

4b9b3361

Ответ 1

Попробуйте inspect модуль. getmembers и различные тесты должны быть полезны.

EDIT:

Например,

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

... и более сложные из которых могут включать специальные проверки имен атрибутов или даже метаклассы;)

Ответ 2

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

properties = props(MyClass)

Ответ 3

myfunc есть атрибут MyClass. То, как оно было найдено при запуске:

myinstance = MyClass()
myinstance.myfunc()

Он ищет атрибут myinstance с именем myfunc, не находит его, видит, что myinstance является экземпляром MyClass и ищет его там.

Таким образом, полный список атрибутов для MyClass:

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

(Обратите внимание, что я использую dir как быстрый и простой способ для перечисления членов класса: его следует использовать только в поисковом режиме, а не в производственном коде)

Если вам нужны только определенные атрибуты, вам нужно будет отфильтровать этот список, используя некоторые критерии, потому что __doc__, __module__ и myfunc не являются особыми, они являются атрибутами в точности так же, как a и b.

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

Также обратите внимание: используя 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']

Ответ 4

MyClass().__class__.__dict__

Однако "правильным" было сделать это через модуль проверки.

Ответ 5

Мое решение получить все атрибуты (не методы) класса (если класс имеет правильно написанную строку документации, в которой четко указаны атрибуты):

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

Этот фрагмент cls.__dict__['__doc__'] извлекает cls.__dict__['__doc__'] документации класса.

Ответ 6

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 в понимании списка. Однако, если один динамически добавляет атрибут mc, например mc.c = "42", этот атрибут не будет отображаться при использовании type(mc) в этой стратегии. Он дает только атрибуты исходного класса.

Чтобы получить полный словарь для экземпляра класса, вам необходимо СОЗДАТЬ словари type(mc).__dict__ и 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('__'))]

Ответ 7

Я не знаю, было ли сделано нечто подобное сейчас или нет, но я сделал хорошую функцию поиска по атрибутам, используя vars(). vars() создает словарь атрибутов класса, через который вы проходите.

class Player():
    def __init__(self):
        self.name = 'Bob'
        self.age = 36
        self.gender = 'Male'

s = vars(Player())
#From this point if you want to print all the attributes, just do print(s)

#If the class has a lot of attributes and you want to be able to pick 1 to see
#run this function
def play():
    ask = input("What Attribute?>: ")
    for key, value in s.items():
        if key == ask:
            print("self.{} = {}".format(key, value))
            break
    else:
        print("Couldn't find an attribute for self.{}".format(ask))

Я разрабатываю довольно масштабное Text Adventure на Python, мой класс Player имеет более 100 атрибутов. Я использую это для поиска определенных атрибутов, которые мне нужно увидеть.

Ответ 8

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

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

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

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

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

Ответ 9

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

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

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

Ответ 10

Вы можете использовать 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('_')]

Ответ 11

Я думаю, это можно сделать без проверки.

Возьмите следующий класс:

 class Test:
   a = 1
   b = 2

   def __init__(self):
     self.c = 42

   @staticmethod
   def toto():
     return "toto"

   def test(self):
     return "test"

Глядя на участников вместе с их типами:

t = Test()
l = [ (x, eval('type(x.%s).__name__' % x)) for x in dir(a) ]

... дает:

[('__doc__', 'NoneType'),
 ('__init__', 'instancemethod'),
 ('__module__', 'str'),
 ('a', 'int'),
 ('b', 'int'),
 ('c', 'int'),
 ('test', 'instancemethod'),
 ('toto', 'function')]

Таким образом, чтобы вывести только переменные, вам просто нужно отфильтровать результаты по типу, а имена не начинаются с '__'. Например

filter(lambda x: x[1] not in ['instancemethod', 'function'] and not x[0].startswith('__'), l)

[('a', 'int'), ('b', 'int'), ('c', 'int')] # actual result

Это.

Примечание: если вы используете Python 3, преобразуйте итераторы в списки.

Если вы хотите более надежный способ сделать это, используйте inspect.

Ответ 12

две функции:

def get_class_attr(Cls) -> []:
    import re
    return [a for a, v in Cls.__dict__.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]

def get_class_attr_val(cls):
    attr = get_class_attr(type(cls))
    attr_dict = {}
    for a in attr:
        attr_dict[a] = getattr(cls, a)
    return attr_dict

использовать:

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

>>> m = MyClass()
>>> get_class_attr_val(m)
{'a': '12', 'b': '34'}

Ответ 13

Вы можете использовать MyClass.__attrs__. Он просто дает все атрибуты этого класса. Ничего более.

Ответ 14

Есть очень простой ответ, который должен быть очевиден: getattr

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

>>> getattr(MyClass, 'a')
'12'

>>> getattr(MyClass, 'myfunc')
<function MyClass.myfunc at 0x10de45378>

Это прекрасно работает как в Python 2.7, так и в Python 3.x.

Если вы хотите список этих предметов, вам все равно нужно будет использовать inspect.

Ответ 15

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

class_name.attribute 

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