Listen Sie die Attribute eines Objekts auf

328

Gibt es eine Möglichkeit, eine Liste von Attributen abzurufen, die in Instanzen einer Klasse vorhanden sind?

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

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

Das gewünschte Ergebnis ist, dass "multi, str" ausgegeben wird. Ich möchte, dass die aktuellen Attribute aus verschiedenen Teilen eines Skripts angezeigt werden.

MadSc13ntist
quelle
75
Praktisch jeder in Python nennt seine Klassen wie NewClass. Sie können den Erwartungen der Leute trotzen, wenn Sie eine Namenskonvention wie verwenden new_class.
Mike Graham
Obwohl es für Menschen interaktiv ist und nicht programmgesteuert verwendet werden kann, help()hilft die Funktion beim Abrufen von Informationen zu Klassen, Funktionen, integrierten Funktionen, Modulen und mehr
ytpillai
1
Relevant: stackoverflow.com/questions/1398022/…
sancho.s ReinstateMonicaCellio
Warum ist keine der Antworten als "Akzeptiert" markiert?
Pfabri

Antworten:

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

Möglicherweise finden Sie auch pprint hilfreich.


quelle
29
Das Problem der Verwendung von Diktaten tauchte gerade bei r / python auf. jemand wies darauf hin, dass vars (a) gleichbedeutend mit einem .__ dict__ ist
David
5
Falls sich jemand wundert, funktioniert dies auch auf Python 2.7
Ben Mordecai
8
Um genau zu sein, werden pprint.pprint(a.__dict__)die Attribute hübsch gedruckt.
smci
1
Auf jeden Fall pprintfunktioniert das NICHT unter Python 2.6.
John Greene
3
Beachten Sie, dass dies nur für benutzerdefinierte Klassen funktioniert, nicht für integrierte Typen oder Erweiterungstypen.
ivan_pozdeev
173
dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__

Dann können Sie testen, mit welchem ​​Typ type() oder ob es sich um eine Methode handelt callable().

Htechno
quelle
dir arbeitete besser an Klassen mit überladenem Attribut get / set
ogurets
dir (Instanz) listet viele Dinge auf, an denen Sie wahrscheinlich nicht interessiert sind
jciloa
Dies war die einzige Funktion, mit der ich alle verfügbaren Attribute für den bostonDatensatz von sklearn erhalten habe - __dict__war leer, obwohl tatsächlich 5 Attribute verfügbar waren
Coruscate5
72

vars(obj) Gibt die Attribute eines Objekts zurück.

rohithpr
quelle
52

Alle vorherigen Antworten sind korrekt. Sie haben drei Möglichkeiten für das, was Sie fragen

  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
quelle
1
vars(foo)Rückkehrfoo.__dict__
Boris
32
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

Dadurch werden natürlich alle Methoden oder Attribute in der Klassendefinition gedruckt. Sie können „private“ Methoden ausschließen , indem Sie i.startwith('__')aufi.startwith('_')

SilentGhost
quelle
24

Das Inspektionsmodul bietet einfache Möglichkeiten zum Inspizieren eines Objekts:

Das Inspect-Modul bietet verschiedene nützliche Funktionen, um Informationen zu Live-Objekten wie Modulen, Klassen, Methoden, Funktionen, Tracebacks, Frame-Objekten und Code-Objekten abzurufen.


Mit getmembers()können Sie alle Attribute Ihrer Klasse zusammen mit ihrem Wert anzeigen. Um private oder geschützte Attribute auszuschließen, verwenden Sie .startswith('_'). Um Methoden oder Funktionen auszuschließen, verwenden Sie inspect.ismethod()oder 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)

Beachten Sie, dass dies ismethod()für das zweite Element von verwendet wird, ida das erste einfach eine Zeichenfolge (deren Name) ist.

Offtopic: Verwenden Sie CamelCase für Klassennamen.

Fermi-Paradoxon
quelle
13

Sie können verwenden dir(your_object), um die Attribute und zu erhaltengetattr(your_object, your_object_attr) die Werte abzurufen

Verwendungszweck :

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

Dies ist besonders nützlich, wenn Ihr Objekt kein __dict__ hat. Wenn dies nicht der Fall ist, können Sie auch var (your_object) ausprobieren

Jason Angel
quelle
11

Es wird oft erwähnt, dass Sie eine vollständige Liste der Attribute auflisten sollten, die Sie verwenden sollten dir(). Beachten Sie jedoch, dass entgegen der landläufigen Meinung dir()nicht alle Attribute hervorgehoben werden. Beispielsweise stellen Sie möglicherweise fest, dass __name__dies in der dir()Liste einer Klasse möglicherweise fehlt , obwohl Sie von der Klasse selbst darauf zugreifen können. Ab dem Dokument dir()( Python 2 , Python 3 ):

Da dir () in erster Linie als Annehmlichkeit für die Verwendung an einer interaktiven Eingabeaufforderung bereitgestellt wird, versucht es, einen interessanten Satz von Namen mehr als einen streng oder konsistent definierten Satz von Namen bereitzustellen, und sein detailliertes Verhalten kann sich zwischen den Releases ändern. Beispielsweise befinden sich Metaklassenattribute nicht in der Ergebnisliste, wenn das Argument eine Klasse ist.

Eine Funktion wie die folgende ist in der Regel vollständiger, obwohl es keine Garantie für die Vollständigkeit gibt, da die von zurückgegebene Liste dir()von vielen Faktoren beeinflusst werden kann, einschließlich der Implementierung der __dir__()Methode oder der Anpassung __getattr__()oder __getattribute__()der Klasse oder eines ihrer übergeordneten Elemente. Weitere Informationen finden Sie unter den bereitgestellten Links.

def dirmore(instance):
    visible = dir(instance)
    visible += [a for a in set(dir(type)).difference(visible)
                if hasattr(instance, a)]
    return sorted(visible)
Michael Ekoka
quelle
9

Wofür willst du das? Es kann schwierig sein, die beste Antwort zu erhalten, ohne Ihre genaue Absicht zu kennen.

  • Es ist fast immer besser, dies manuell zu tun, wenn Sie eine Instanz Ihrer Klasse auf eine bestimmte Weise anzeigen möchten. Dies beinhaltet genau das, was Sie wollen und nicht das, was Sie nicht wollen, und die Reihenfolge ist vorhersehbar.

    Wenn Sie nach einer Möglichkeit suchen, den Inhalt einer Klasse anzuzeigen, formatieren Sie die Attribute, die Sie interessieren, manuell und geben Sie diese als __str__oder __repr__Methode für Ihre Klasse an.

  • Wenn Sie wissen möchten, welche Methoden und solche für ein Objekt vorhanden sind, um zu verstehen, wie es funktioniert, verwenden Sie help. help(a)zeigt Ihnen eine formatierte Ausgabe über die Klasse des Objekts basierend auf den Dokumentzeichenfolgen.

  • direxistiert zum programmgesteuerten Abrufen aller Attribute eines Objekts. (Der Zugriff __dict__bewirkt etwas, das ich als dasselbe gruppieren würde, das ich aber nicht selbst verwenden würde.) Dies beinhaltet jedoch möglicherweise nicht die gewünschten Dinge und möglicherweise auch die Dinge, die Sie nicht möchten. Es ist unzuverlässig und die Leute denken, sie wollen es viel öfter als sie.

  • Etwas orthogonal gibt es derzeit nur sehr wenig Unterstützung für Python 3. Wenn Sie daran interessiert sind, echte Software zu schreiben, möchten Sie Inhalte von Drittanbietern wie numpy, lxml, Twisted, PIL oder eine beliebige Anzahl von Webframeworks, die Python 3 noch nicht unterstützen und zu früh keine Pläne haben. Die Unterschiede zwischen 2.6 und 3.x sind gering, aber der Unterschied in der Bibliotheksunterstützung ist groß.

Mike Graham
quelle
4
Ich möchte nur darauf hinweisen, dass fünf Jahre später (jetzt) ​​alle von Ihnen erwähnten Module von Drittanbietern Python3 unterstützen. Quelle: python3wos.appspot.com
pzkpfw
8

Es gibt mehr als einen Weg, dies zu tun:

#! /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) )

Beim Ausführen erzeugt dieser Code:

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
quelle
2
Warum wurde diese Antwort abgelehnt? Zum Debuggen funktioniert dir ziemlich gut!
Dunatotatos
Funktioniert ziemlich gut mit Python 2.7.x. Genau das, was ich wollte.
Davidson Lima
7

Bitte beachten Sie das Python-Shell-Skript, das nacheinander ausgeführt wurde. Hier erhalten Sie die Attribute einer Klasse im durch Komma getrennten Zeichenfolgenformat.

>>> 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/>

Ich benutze Python 3.4

Lokesh Kumar
quelle
Und wenn Sie wollen, kann nur die Liste nur verwenden a.__dict__.keys(). Wenn Sie jedoch wissen möchten, ob ein Objekt ein bestimmtes Attribut hat, können Sie es verwenden hasattr.
Berna1111
4

Zusätzlich zu diesen Antworten werde ich eine Funktion (Python 3) einfügen, mit der praktisch die gesamte Struktur eines beliebigen Werts ausgespuckt werden kann. Es wird verwendet dir, um die vollständige Liste der Eigenschaftsnamen zu erstellen, und wird dann getattrmit jedem Namen verwendet. Es zeigt den Typ jedes Mitglieds des Werts an und wenn möglich auch das gesamte Mitglied:

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

Nun sollte eine der folgenden Aussagen einen Einblick geben:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... etc.
Gershom
quelle
Wow, das ist ein Juwel!
Pfabri
Ja, das war ein Lebensretter. Ich konnte nicht herausfinden, warum ich diese Listen nicht einfach entpacken konnte und sicher genug, dass der Typ die Eigenschaft " Slots " vom Typ "Tupel" hat. Hier ist der Slots- Wert: ["nsname", "hostmaster", "serial", "refresh", "retry", "expires", "minttl", "ttl"]
Mik R vor
3

Attribute eines Objekts abrufen

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)

Ausgabe

['__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
Gesegnet
quelle
1

Wie vor der Verwendung geschrieben, obj.__dict__können häufige Fälle behandelt werden, aber einige Klassen verfügen nicht über das __dict__Attribut und die Verwendung __slots__(hauptsächlich aus Gründen der Speichereffizienz).

Beispiel für eine belastbarere Vorgehensweise:

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

Die Ausgabe dieses Codes:

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

Hinweis 1:
Python ist eine dynamische Sprache und es ist immer besser, die Klassen zu kennen, aus denen Sie die Attribute abrufen möchten, da selbst dieser Code in einigen Fällen fehlen kann.

Hinweis 2:
Dieser Code gibt nur Instanzvariablen aus, dh Klassenvariablen werden nicht bereitgestellt. zum Beispiel:

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

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

Code-Ausgaben:

{'path': '/questions'}

Dieser Code druckt das urlKlassenattribut nicht und lässt möglicherweise die gewünschten Klassenattribute aus.
Manchmal denken wir vielleicht, dass ein Attribut ein Instanzmitglied ist, aber es wird in diesem Beispiel nicht angezeigt und wird auch nicht angezeigt.

ShmulikA
quelle
2
Eine Klasse kann __dict__ und haben __slots__ , also möchten Sie wahrscheinlich beides versuchen und nicht nur das Diktat.
cz
1
  • Verwenden __dict__oder vars funktioniert nicht, weil es fehlt__slots__ .
  • Verwenden __dict__und __slots__ funktioniert nicht, weil es fehlt__slots__ Basisklassen .
  • Verwenden dir funktioniert nicht da sie Klassenattribute wie Methoden oder Eigenschaften sowie die Objektattribute enthält.
  • Verwenden varsist gleichbedeutend mit Verwenden __dict__.

Das ist das Beste, was ich habe:

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
quelle
Wenden wir diese Funktion auf eine einfache Klasse an: Klasse C: def __init __ (self): print ("created") i = 42 Warum enthält Ihr Code eine leere Liste für eine solche Klasse? (Ich meine, wenn o = C (), dann ist get_attrs (o) leer.) Dies gilt auch für get_attrs ("mystr")
ged
0
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]
shammerw0w
quelle
Es funktioniert nicht mit Klassenattributnamen, die mit einem Großbuchstaben oder einem einzelnen Unterstrich beginnen.
fviktor
0

Weitere Informationen finden Sie in der folgenden Python-Shell-Skriptausführung nacheinander. Sie bietet die Lösung von der Erstellung der Klasse bis zum Extrahieren der Feldnamen von Instanzen.

>>> 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
quelle
Wir können auch überprüfen, ob die einzelnen Attribute aufrufbar sind.
Besuchen Sie
-4

__attr__ gibt die Liste der Attribute einer Instanz an.

>>> 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/'
>>>
Vivek
quelle
Funktioniert nicht immer. Außerdem schreiben Sie __attr__in die Beschreibung, verwenden sie aber __attrs__im Code. Beides hat bei mir nicht funktioniert (werkzeug.datastructures.FileStorage)
Jonas