549 Stimmen

Auflistung der Attribute eines Objekts

Gibt es eine Möglichkeit, eine Liste von Attributen abzurufen, die auf 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 dies sehen, um die aktuellen Attribute aus verschiedenen Teilen eines Skripts zu überprüfen.

99 Stimmen

Praktisch jeder in Python benennt seine Klassen wie NewClass. Du könntest die Erwartungen der Leute herausfordern, wenn du eine Benennungskonvention wie new_class verwendest.

1 Stimmen

Auch wenn es interaktiv für Menschen ist und nicht programmgesteuert verwendet werden kann, hilft die help()-Funktion bei der Beschaffung von Informationen über Klassen, Funktionen, integrierte Funktionen, Module und mehr

2 Stimmen

8voto

Lokesh kumar Punkte 117

Bitte sehen Sie sich das Python-Shell-Skript an, das sequenziell ausgeführt wurde. Hier erhalten Sie die Attribute einer Klasse im String-Format, die durch Komma getrennt sind.

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

Ich benutze Python 3.4

0 Stimmen

Und wenn Sie nur die Liste wünschen, können Sie einfach a.__dict__.keys() verwenden. Wenn Sie jedoch wissen möchten, ob ein Objekt ein bestimmtes Attribut hat, können Sie hasattr verwenden.

7voto

Gershom Maes Punkte 6241

Zusätzlich zu diesen Antworten werde ich eine Funktion (Python 3) hinzufügen, um praktisch die gesamte Struktur eines Werts auszugeben. Sie verwendet dir, um die vollständige Liste der Eigenschaftsnamen festzulegen, und verwendet dann getattr mit jedem Namen. Sie zeigt den Typ jedes Elements des Werts an und zeigt, wenn möglich, auch das gesamte Element:

import json

def get_info(obj):

  type_name = type(obj).__name__
  print('Der Wert ist vom Typ {}!'.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('{} hat die Eigenschaft "{}" vom Typ "{}"'.format(type_name, prop_name, prop_val_type_name))

    try:
      val_as_str = json.dumps([ prop_val ], indent=2)[1:-1]
      print('  Hier ist der {} Wert: {}'.format(prop_name, val_as_str))
    except:
      pass

Jetzt sollte einer der folgenden Einblicke geben:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... usw.

1 Stimmen

Yeah das war ein Lebensretter. konnte nicht herausfinden, warum ich diese Listen nicht einfach auspacken konnte und tatsächlich hat dieser Typ die Eigenschaft "slots" vom Typ "tuple" Hier ist der slots Wert: [ "nsname", "hostmaster", "serial", "refresh", "retry", "expires", "minttl", "ttl" ]

3voto

c z Punkte 6152
  • Die Verwendung von __dict__ oder vars funktioniert nicht, weil __slots__ fehlt.
  • Die Verwendung von __dict__ und __slots__ funktioniert nicht, weil __slots__ von Basisklassen ausgelassen wird.
  • Die Verwendung von dir funktioniert nicht, weil es Klassenattribute wie Methoden oder Eigenschaften sowie Objektattribute enthält.
  • Die Verwendung von vars entspricht der Verwendung von __dict__.

Dies 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, "Mehrere __dicts__?"
                attrs.update( v )
                has_dict = True
            else:
                attrs[slot] = v

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

    return attrs

0 Stimmen

Lassen Sie uns diese Funktion auf eine einfache Klasse anwenden: class C: def __init__(self): print("created") i = 42 Warum liefert Ihr Code eine leere Liste für eine solche Klasse? (Ich meine, wenn o = C() dann ist get_attrs(o) leer) Es hat auch für get_attrs("mystr") geleert.

0 Stimmen

@ged Da deine einfache Klasse keine Instanz felder enthält (wie in der Frage beschrieben), ist das Ergebnis leer. Ich bin mir nicht sicher, was du erwartest zu sehen.

2voto

Blessed Punkte 29

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))                   #Gesamte Liste der Attribute von new_object
attr_value = new_object.__dict__         
print(attr_value)                        #Dictionary von Attribut und Wert für new_class                   

for attr in attr_value:                  #Attribute in 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

1voto

ShmulikA Punkte 3172

Wie bereits beschrieben, kann obj.__dict__ in den meisten Fällen verwendet werden, aber einige Klassen haben nicht das __dict__-Attribut und verwenden stattdessen __slots__ (meistens aus Gründen der Speffizienz).

Beispiel für eine robustere Methode, dies zu tun:

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

Ausgabe dieses Codes:

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

Hinweis1:
Python ist eine dynamische Sprache und es ist immer besser, die Klassen zu kennen, von denen Sie die Attribute erhalten möchten, da selbst dieser Code einige Fälle übersehen könnte.

Hinweis2:
Dieser Code gibt nur Instanzvariablen aus, das bedeutet, Klassenvariablen werden nicht angezeigt. Zum Beispiel:

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

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

Der Code gibt aus:

{'path': '/questions'}

Dieser Code wird das url-Klassenattribut nicht ausgeben und könnte gewünschte Klassenattribute auslassen.
Manchmal denken wir, dass ein Attribut ein Instanzattribut ist, aber es ist keins und würde in diesem Beispiel nicht angezeigt werden.

3 Stimmen

Eine Klasse kann __dict__ und __slots__ haben, daher sollten Sie wahrscheinlich beide ausprobieren, anstatt nur das Dictionary zu verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X