Ich möchte ein dynamisches Objekt (innerhalb eines anderen Objekts) in Python erstellen und ihm dann Attribute hinzufügen.
Ich habe es versucht:
obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')
aber das hat nicht funktioniert.
Irgendwelche Ideen?
bearbeiten:
Ich setze die Attribute aus einer for
Schleife, die eine Liste von Werten durchläuft, z
params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()
for p in params:
obj.a.p # where p comes from for loop variable
In dem obigen Beispiel , das ich bekommen würde obj.a.attr1
, obj.a.attr2
, obj.a.attr3
.
Ich habe die setattr
Funktion verwendet, weil ich nicht wusste, wie man mit obj.a.NAME
einer for
Schleife umgeht.
Wie würde ich das Attribut basierend auf dem Wert von p
im obigen Beispiel festlegen ?
python
class
object
attributes
John
quelle
quelle
a = object()
und Sie brauchenobj.a = object()
. Ich spreche wieder über das Beispiel, in Ihrem eigentlichen Code könnte ein Objekt innerhalb eines Objekts nützlich sein.Antworten:
Sie könnten mein altes Bunch- Rezept verwenden, aber wenn Sie keine "Bündelklasse" erstellen möchten, gibt es in Python bereits eine sehr einfache - alle Funktionen können beliebige Attribute haben (einschließlich Lambda-Funktionen). Also funktioniert folgendes:
Ob der Verlust an Klarheit im Vergleich zum ehrwürdigen
Bunch
Rezept in Ordnung ist, ist eine Stilentscheidung, die ich natürlich Ihnen überlassen werde.quelle
lambda: 23
), so dass solche Expertenlambda
s für diesen Zweck verwenden würde sich vermutlich nicht wie "ein Hack" anfühlen. Persönlich mag ichlambda
Python nicht sehr - aber das ist eine Frage des persönlichen Geschmacks.lambda
Muster für Ihren Anwendungsfall geeignet ist oder nicht, dazu führen, dass Sie feststellen, dass etwas, das Sie ursprünglich als Daten angesehen hatten, ohnehin eher einer Funktion ähnelt - oder auf jeden Fall einem Funktor.from argparse import Namespace
obwohl ich wünschte, es würde woanders leben * zBcollection
) - wieder einen jetzt existierenden Typ wiederverwenden, nur einen besseren, und trotzdem die Erstellung neuer Typen vermeiden. Aber es war damals nicht da :-).Das integrierte
object
Gerät kann instanziiert werden, es können jedoch keine Attribute festgelegt werden. (Ich wünschte, es könnte genau zu diesem Zweck möglich sein.) Es muss keine__dict__
Attribute enthalten.Ich mache im Allgemeinen einfach Folgendes:
Wenn ich kann, gebe ich der
Object
Klasse einen aussagekräftigeren Namen, je nachdem, welche Art von Daten ich in sie einfüge.Einige Leute machen eine andere Sache, indem sie eine Unterklasse verwenden
dict
, die den Zugriff auf Attribute auf die Schlüssel ermöglicht. (d.key
stattd['key']
)Bearbeiten : Für die Ergänzung Ihrer Frage ist die Verwendung
setattr
in Ordnung. Sie können es einfach nichtsetattr
fürobject()
Instanzen verwenden.quelle
foo = object()
funktioniert, aber man kann einfach nicht viel damittype....
oder Lambda war nie mein Favorit, wie Text Erbrechen in meinem Code. Diese Idee eignet sich jedoch hervorragend für die Verwendung von Objekten zum Speichern von Eigenschaften. Lässt Code besser lesbar, wenn ich Lambda sehe. Ich verlangsame meinen Lesevorgang auf 25%, während Ihr Weg absolut sinnvoll ist! Vielen Dank.Struct
den Namen der Klasse zu verwenden, um es offensichtlicher zu machen. Ersparte mir eine Menge Tippen["
und"]
, Prost!types.SimpleNamespace
In Python 3.3+ gibt es eine Klasse :collections.namedtuple
,typing.NamedTuple
könnte für unveränderliche Objekte verwendet werden. PEP 557 - Datenklassen schlagen eine veränderbare Alternative vor.Für eine umfassendere Funktionalität können Sie das Paket ausprobieren
attrs
. Siehe ein Beispiel für die Verwendung .quelle
argparse.Namespace
Klasse ausprobierenattrs
Paket unterstützt Python 2.7Es gibt einige Möglichkeiten, um dieses Ziel zu erreichen. Grundsätzlich benötigen Sie ein Objekt, das erweiterbar ist.
quelle
obj.a = type('', (), {})
Das
mock
Modul ist grundsätzlich dafür gemacht.quelle
unittest.Mock
ist ein Teil der Standardbibliothek seit Python 3.3 ( docs.python.org/3/library/unittest.mock.html )mock
darin wollen. Fühlt sich für mich einfach komisch an.Jetzt können Sie Folgendes tun (nicht sicher, ob es die gleiche Antwort wie bei Evilpie ist):
quelle
Versuchen Sie den folgenden Code:
quelle
Sie können ein Klassenobjekt auch direkt verwenden. Es wird ein Namespace erstellt:
quelle
wie die Dokumente sagen :
Sie könnten einfach eine Dummy-Klasseninstanz verwenden.
quelle
Diese Lösungen sind beim Testen sehr hilfreich. Aufbauend auf den Antworten aller anderen mache ich dies in Python 2.7.9 (ohne statische Methode erhalte ich einen TypeError (ungebundene Methode ...):
quelle
Welche Objekte verwenden Sie? Habe das gerade mit einer Beispielklasse versucht und es hat gut funktioniert:
Und ich bekam
123
als Antwort.Die einzige Situation, in der ich sehe, dass dies fehlschlägt, ist, wenn Sie es versuchen
setattr
mit einem eingebauten Objekt .Update: Aus dem Kommentar geht hervor, dass Folgendes wiederholt wird: Warum können Sie dem Objekt in Python keine Attribute hinzufügen?
quelle
Ich komme zu spät am Tag, aber hier ist mein Pennyworth mit einem Objekt, das zufällig einige nützliche Pfade in einer App enthält, aber Sie können es für alles anpassen, wo Sie eine Art Diktat von Informationen wünschen, auf die Sie mit getattr und Punktnotation zugreifen können (worum es meiner Meinung nach bei dieser Frage wirklich geht):
Das ist cool, weil jetzt:
Dies verwendet also das Funktionsobjekt wie die obigen Antworten, verwendet jedoch die Funktion, um die Werte abzurufen (Sie können es weiterhin verwenden,
(getattr, x_path, 'repository')
anstattx_path('repository')
es zu bevorzugen).quelle
Wenn wir alle Attribute und Werte zusammen bestimmen und aggregieren können, bevor wir das verschachtelte Objekt erstellen, können wir eine neue Klasse erstellen, die beim Erstellen ein Wörterbuchargument verwendet.
Wir können auch Schlüsselwortargumente zulassen. Siehe diesen Beitrag .
quelle
quelle
Anders sehe ich das so:
quelle
class a: pass
die gesamte erforderliche Leistung bietet.