Список атрибутів об’єкта


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". Я хочу, щоб це бачило поточні атрибути з різних частин сценарію.


75
Практично всі в Python називають свої класи, як NewClass. Ви можете оскаржити очікування людей, якщо використовуєте конвенцію про іменування на кшталт new_class.
Майк Грем

Незважаючи на те, що він є інтерактивним для людини і не може бути використаний програмно, help()функція допомагає отримувати інформацію про класи, функції, вбудовані модулі та інше
ytpillai


Чому жодна відповідь не позначена як "Прийнято"?
pfabri

Відповіді:


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
Бен Мордекай

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().


dir працював краще на заняттях із перевантаженим атрибутом get / set
ogurets

dir (екземпляр) перелічує багато речей, які вас, мабуть, не цікавлять
jciloa

Це була єдина функція, яка отримала мені всі доступні атрибути на bostonнаборі даних від sklearn - __dict__була порожня, коли насправді було 5 доступних атрибутів
Coruscate5


53

Усі попередні відповіді правильні, у вас є три варіанти того, що ви запитуєте

  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'}

1
vars(foo)поверненняfoo.__dict__
Борис

32
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

Це звичайно буде надрукувати будь-які методи або атрибути у визначенні класу. Ви можете виключити "приватні" методи, перейшовши i.startwith('__')наi.startwith('_')


24

Модуль перевірки забезпечує прості способи огляду об’єкта:

Модуль перевірки надає кілька корисних функцій, які допомагають отримувати інформацію про живі об'єкти, такі як модулі, класи, методи, функції, відстеження, рамкові об'єкти та об'єкти коду.


Використовуючи 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оскільки перший - це просто рядок (його назва).

Offtopic: Використовуйте 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$

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.

Нічого собі, це дорогоцінний камінь!
pfabri

так, це був рятівник. не вдалося зрозуміти, чому це я не міг легко розпакувати ці списки, і впевнений, що в достатньому типі є властивість " slots " типу "кортеж" Ось значення слотів : ["nsname", "hostmaster", "serial", "refresh", "повторити", "закінчується", "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атрибут класу і може опускати потрібні атрибути класу.
Іноді ми можемо вважати, що атрибут є членом екземпляра, але він не є і не буде показаний на цьому прикладі.


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

Давайте застосуємо цю функцію до простого класу: клас C: def __init __ (само): print ("створено") i = 42 Чому ваш код дає порожній список для такого класу? (Я маю в виду , якщо про = C () , то get_attrs (о) порожньо) Він також зробив для get_attrs ( "mystr")
GED

0
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]

Це не працює з іменами атрибутів класу, що починаються з великої літери або окремого підкреслення.
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']
>>>

Ми також можемо перевірити для callablilty кожного attributes.visit stackoverflow.com/questions/1398022 / ...
hygull

-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)
Йонас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.