Список атрибутов объекта

330

Есть ли способ получить список атрибутов, которые существуют в экземплярах класса?

class new_class():
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

a = new_class(2)
print(', '.join(a.SOMETHING))

Желаемый результат заключается в том, что «multi, str» будет выводиться. Я хочу, чтобы это видеть текущие атрибуты из различных частей скрипта.

MadSc13ntist
источник
75
Практически все в Python называют свои классы как NewClass. Вы можете бросить вызов ожиданиям людей, если будете использовать соглашение об именах, например new_class.
Майк Грэм,
Несмотря на то, что он интерактивный и не может использоваться программно, help()функция помогает получать информацию о классах, функциях, встроенных функциях, модулях и т. Д.
ytpillai
1
Соответствует: stackoverflow.com/questions/1398022/…
sancho.s ReinstateMonicaCellio
Почему ни один из ответов не помечен как «Принят»?
Пфабри

Ответы:

295
>>> class new_class():
...   def __init__(self, number):
...     self.multi = int(number) * 2
...     self.str = str(number)
... 
>>> a = new_class(2)
>>> a.__dict__
{'multi': 4, 'str': '2'}
>>> a.__dict__.keys()
dict_keys(['multi', 'str'])

Вы также можете найти pprint полезным.


источник
29
Проблема использования dict только что появилась на r / python. кто-то указал, что vars (a) эквивалентен .__ dict__
Дэвид
5
Если кому-то интересно, это работает и на Python 2.7
Ben Mordecai
8
Чтобы быть конкретным, pprint.pprint(a.__dict__)делает симпатичный отпечаток на атрибутах.
smci
1
Определенно, pprintэто не работает на Python 2.6.
Джон Грин
3
Обратите внимание, что это работает только для пользовательских классов, а не для встроенных или расширенных типов.
ivan_pozdeev
173
dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__

Затем вы можете проверить, какой тип с type()или с методом callable().

Htechno
источник
dir работал лучше на классах с перегруженным атрибутом get / set
ogurets
dir (instance) перечисляет много вещей, которые вам, вероятно, не интересны
jciloa
Это была единственная функция, которая bostonдоставляла мне все доступные атрибуты в наборе данных из sklearn - __dict__была пуста, когда на самом деле было 5 доступных атрибутов
Coruscate5
72

vars(obj) возвращает атрибуты объекта.

rohithpr
источник
54

Все предыдущие ответы верны, у вас есть три варианта того, что вы спрашиваете

  1. dir()

  2. vars()

  3. __dict__

>>> dir(a)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']
>>> vars(a)
{'multi': 4, 'str': '2'}
>>> a.__dict__
{'multi': 4, 'str': '2'}
grepit
источник
1
vars(foo)возвращаетсяfoo.__dict__
Борис
32
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

Это, конечно, напечатает любые методы или атрибуты в определении класса. Вы можете исключить «частные» методы путем изменения i.startwith('__')вi.startwith('_')

SilentGhost
источник
24

Модуль проверки обеспечивает простые способы проверки объекта:

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


Используя getmembers()вы можете увидеть все атрибуты вашего класса, а также их значение. Для исключения приватных или защищенных атрибутов используйте .startswith('_'). Чтобы исключить методы или функции, используйте inspect.ismethod()или inspect.isfunction().

import inspect


class NewClass(object):
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

    def func_1(self):
        pass


a = NewClass(2)

for i in inspect.getmembers(a):
    # Ignores anything starting with underscore 
    # (that is, private and protected attributes)
    if not i[0].startswith('_'):
        # Ignores methods
        if not inspect.ismethod(i[1]):
            print(i)

Обратите внимание, что ismethod()используется для второго элемента, iтак как первый - это просто строка (его имя).

Оффтоп: используйте CamelCase для имен классов.

Парадокс ферми
источник
13

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

использование :

for att in dir(your_object):
    print (att, getattr(your_object,att))

Это особенно полезно, если у вашего объекта нет __dict__. Если это не так, вы можете попробовать var (your_object) также

Джейсон Ангел
источник
11

Часто упоминается, что для получения полного списка атрибутов вы должны использовать dir(). Однако обратите внимание, что вопреки распространенному мнению dir(), не выявляет все атрибуты. Например, вы можете заметить, что __name__может отсутствовать в dir()списке класса, даже если вы можете получить к нему доступ из самого класса. Из документа dir()( Python 2 , Python 3 ):

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

Функция как ниже имеет тенденцию быть более полным, хотя нет никакой гарантии полноты , так как список возвращенного dir()может зависеть от многих факторов , в том числе реализации __dir__()методы, или настройке __getattr__()или __getattribute__()на классе или одного из его родителей. Смотрите предоставленные ссылки для более подробной информации.

def dirmore(instance):
    visible = dir(instance)
    visible += [a for a in set(dir(type)).difference(visible)
                if hasattr(instance, a)]
    return sorted(visible)
Майкл Экока
источник
9

Зачем тебе это? Может быть трудно получить лучший ответ, не зная вашего точного намерения.

  • Почти всегда лучше делать это вручную, если вы хотите отобразить экземпляр вашего класса особым образом. Это будет включать именно то, что вы хотите, а не то, что вы не хотите, и порядок будет предсказуемым.

    Если вы ищете способ отображения содержимого класса, вручную отформатируйте атрибуты, которые вас интересуют, и предоставьте это как метод __str__или __repr__для вашего класса.

  • Если вы хотите узнать, какие методы существуют для объекта, чтобы понять, как он работает, используйте help. help(a)покажет вам форматированный вывод о классе объекта на основе его строк документации.

  • dirсуществует для программного получения всех атрибутов объекта. (Доступ - __dict__это то, что я бы сгруппировал как то же самое, но я бы не использовал сам.) Однако это может не включать в себя то, что вы хотите, и это может включать в себя то, что вы не хотите. Это ненадежно, и люди думают, что хотят этого гораздо чаще, чем хотят.

  • На некотором ортогональном примечании, в настоящее время очень мало поддержки Python 3. Если вы заинтересованы в написании реального программного обеспечения, вам понадобятся сторонние материалы, такие как numpy, lxml, Twisted, PIL или любое количество веб-фреймворков, которые еще не поддерживают Python 3 и не планируют делать это слишком рано. Различия между 2.6 и веткой 3.x невелики, но разница в поддержке библиотек огромна.

Майк Грэм
источник
4
Я хотел бы отметить, что пять лет спустя (сейчас), я полагаю, все сторонние модули, о которых вы упомянули, поддерживают python3. Источник: python3wos.appspot.com
pzkpfw
8

Существует несколько способов сделать это:

#! /usr/bin/env python3
#
# This demonstrates how to pick the attiributes of an object

class C(object) :

  def __init__ (self, name="q" ):
    self.q = name
    self.m = "y?"

c = C()

print ( dir(c) )

При запуске этот код выдает:

jeffs@jeff-desktop:~/skyset$ python3 attributes.py 
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',      '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm', 'q']

jeffs@jeff-desktop:~/skyset$
user1928764
источник
2
Почему этот ответ был отклонен? В целях отладки dir работает довольно хорошо!
Дунатотатос
Довольно работает с Python 2.7.x. Именно то, что я хотел.
Дэвидсон Лима
7

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

>>> class new_class():
...     def __init__(self, number):
...         self.multi = int(number)*2
...         self.str = str(number)
... 
>>> a = new_class(4)
>>> ",".join(a.__dict__.keys())
'str,multi'<br/>

Я использую Python 3.4

Локеш Кумар
источник
А если хотите, можете использовать только список a.__dict__.keys(). Однако, если вы хотите знать, имеет ли объект определенный атрибут, который вы можете использовать hasattr.
berna1111
4

В дополнение к этим ответам я включу функцию (python 3) для выдачи практически всей структуры любого значения. Он использует dirдля создания полного списка имен свойств, а затем использует getattrс каждым именем. Он отображает тип каждого элемента значения и, когда возможно, также отображает весь элемент:

import json

def get_info(obj):

  type_name = type(obj).__name__
  print('Value is of type {}!'.format(type_name))
  prop_names = dir(obj)

  for prop_name in prop_names:
    prop_val = getattr(obj, prop_name)
    prop_val_type_name = type(prop_val).__name__
    print('{} has property "{}" of type "{}"'.format(type_name, prop_name, prop_val_type_name))

    try:
      val_as_str = json.dumps([ prop_val ], indent=2)[1:-1]
      print('  Here\'s the {} value: {}'.format(prop_name, val_as_str))
    except:
      pass

Теперь любое из следующего должно дать понимание:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... etc.
Гирсам
источник
Вау, это драгоценный камень!
Пфабри
да, это был спасатель Я не мог понять, почему это, я не мог легко распаковать эти списки и, конечно же, тип имеет свойство " slots " типа "tuple". Вот значение slots : ["nsname", "hostmaster", "serial", "refresh", "retry", "expires", "minttl", "ttl"]
Mik R
3

Получить атрибуты объекта

class new_class():
    def __init__(self, number):
    self.multi = int(number) * 2
    self.str = str(number)

new_object = new_class(2)                
print(dir(new_object))                   #total list attributes of new_object
attr_value = new_object.__dict__         
print(attr_value)                        #Dictionary of attribute and value for new_class                   

for attr in attr_value:                  #attributes on  new_class
    print(attr)

Вывод

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__','__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']

{'multi': 4, 'str': '2'}

multi
str
Блажен
источник
1

Как написано перед использованием, obj.__dict__можно обрабатывать общие случаи, но некоторые классы не имеют __dict__атрибута и использования __slots__(в основном для эффективности памяти).

пример более гибкого способа сделать это:

class A(object):
    __slots__ = ('x', 'y', )
    def __init__(self, x, y):
        self.x = x
        self.y = y


class B(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y


def get_object_attrs(obj):
    try:
        return obj.__dict__
    except AttributeError:
        return {attr: getattr(obj, attr) for attr in obj.__slots__}


a = A(1,2)
b = B(1,2)
assert not hasattr(a, '__dict__')

print(get_object_attrs(a))
print(get_object_attrs(b))

вывод этого кода:

{'x': 1, 'y': 2}
{'x': 1, 'y': 2}

Примечание 1:
Python - это динамический язык, и всегда лучше знать классы, от которых вы пытаетесь получить атрибуты, поскольку даже этот код может пропустить некоторые случаи.

Примечание 2:
этот код выводит только переменные экземпляра, то есть переменные класса не предоставляются. например:

class A(object):
    url = 'http://stackoverflow.com'
    def __init__(self, path):
        self.path = path

print(A('/questions').__dict__)

кодовые выходы:

{'path': '/questions'}

Этот код не печатает urlатрибут класса и может пропустить требуемые атрибуты класса.
Иногда мы можем думать, что атрибут является членом экземпляра, но это не так и не будет показано в этом примере.

ShmulikA
источник
2
Класс может иметь __dict__ и __slots__ , так что вы, вероятно, хотите попробовать оба, а не просто диктат.
CZ
1
  • Использование __dict__или vars не работает, потому что он пропускает __slots__.
  • Использование __dict__и __slots__ не работает, потому что он пропускает __slots__из базовых классов.
  • Использование dir не работает, поскольку оно включает атрибуты класса, такие как методы или свойства, а также атрибуты объекта.
  • Использование varsэквивалентно использованию __dict__.

Это лучшее, что у меня есть:

from typing import Dict

def get_attrs( x : object ) -> Dict[str, object]:
    mro      = type( x ).mro()
    attrs    = { }
    has_dict = False
    sentinel = object()

    for klass in mro:
        for slot in getattr( klass, "__slots__", () ):
            v = getattr( x, slot, sentinel )

            if v is sentinel:
                continue

            if slot == "__dict__":
                assert not has_dict, "Multiple __dicts__?"
                attrs.update( v )
                has_dict = True
            else:
                attrs[slot] = v

    if not has_dict:
        attrs.update( getattr( x, "__dict__", { } ) )

    return attrs
CZ
источник
Давайте применим эту функцию к простому классу spome: класс C: def __init __ (self): print ("созданный") i = 42 Почему ваш код дает пустой список для такого класса? (Я имею в виду, если o = C (), тогда get_attrs (o) пусто) Это также было сделано для get_attrs ("mystr")
ged
0
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]
shammerw0w
источник
Он не работает с именами атрибутов класса, начинающимися с заглавной буквы или одного подчеркивания.
fviktor
0

Пожалуйста, посмотрите следующее выполнение сценариев оболочки Python последовательно, это даст решение от создания класса до извлечения имен полей экземпляров.

>>> class Details:
...       def __init__(self,name,age):
...           self.name=name
...           self.age =age
...       def show_details(self):
...           if self.name:
...              print "Name : ",self.name
...           else:
...              print "Name : ","_"
...           if self.age:
...              if self.age>0:
...                 print "Age  : ",self.age
...              else:
...                 print "Age can't be -ve"
...           else:
...              print "Age  : ","_"
... 
>>> my_details = Details("Rishikesh",24)
>>> 
>>> print my_details
<__main__.Details instance at 0x10e2e77e8>
>>> 
>>> print my_details.name
Rishikesh
>>> print my_details.age
24
>>> 
>>> my_details.show_details()
Name :  Rishikesh
Age  :  24
>>> 
>>> person1 = Details("",34)
>>> person1.name
''
>>> person1.age
34
>>> person1.show_details
<bound method Details.show_details of <__main__.Details instance at 0x10e2e7758>>
>>> 
>>> person1.show_details()
Name :  _
Age  :  34
>>>
>>> person2 = Details("Rob Pike",0)
>>> person2.name
'Rob Pike'
>>> 
>>> person2.age
0
>>> 
>>> person2.show_details()
Name :  Rob Pike
Age  :  _
>>> 
>>> person3 = Details("Rob Pike",-45)
>>> 
>>> person3.name
'Rob Pike'
>>> 
>>> person3.age
-45
>>> 
>>> person3.show_details()
Name :  Rob Pike
Age can't be -ve
>>>
>>> person3.__dict__
{'age': -45, 'name': 'Rob Pike'}
>>>
>>> person3.__dict__.keys()
['age', 'name']
>>>
>>> person3.__dict__.values()
[-45, 'Rob Pike']
>>>
hygull
источник
Мы также можем проверить callablilty каждого атрибута.
Visit
-4

__attr__ дает список атрибутов экземпляра.

>>> import requests
>>> r=requests.get('http://www.google.com')
>>> r.__attrs__
['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
>>> r.url
'http://www.google.com/'
>>>
Вивек
источник
Не всегда работает Также вы пишете __attr__в описании, но используете __attrs__в коде. Ни один из них не работал для меня (werkzeug.datastructures.FileStorage)
Джонас