433 Stimmen

Wie kann ich ein Objekt erstellen und ihm Attribute hinzufügen?

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, in der eine Liste von Werten durchlaufen wird, z. B.

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 würde ich Folgendes erhalten obj.a.attr1 , obj.a.attr2 , obj.a.attr3 .

Ich habe die setattr Funktion, weil ich nicht wusste, wie man die obj.a.NAME von einer for Schleife.

Wie würde ich das Attribut auf der Grundlage des Wertes von p im obigen Beispiel?

3voto

HarlemSquirrel Punkte 7166

Wenn wir alle Attribute und Werte vor der Erstellung des verschachtelten Objekts ermitteln und zusammenfassen können, könnten wir eine neue Klasse erstellen, die bei der Erstellung ein Wörterbuchargument annimmt.

# python 2.7

class NestedObject():
    def __init__(self, initial_attrs):
        for key in initial_attrs:
            setattr(self, key, initial_attrs[key])

obj = someobject
attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' }
obj.a = NestedObject(attributes)
>>> obj.a.attr1
'val1'
>>> obj.a.attr2
'val2'
>>> obj.a.attr3
'val3'

Wir können auch Schlüsselwortargumente zulassen. Siehe ce poste .

class NestedObject(object):
    def __init__(self, *initial_attrs, **kwargs):
        for dictionary in initial_attrs:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])

obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3')

1voto

jneves Punkte 964

Welche Objekte verwenden Sie? Ich habe das gerade mit einer Beispielklasse ausprobiert und es hat gut funktioniert:

class MyClass:
  i = 123456
  def f(self):
    return "hello world"

b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test

Und ich habe 123 als die Antwort.

Die einzige Situation, in der ich sehe, dass dies scheitert, ist, wenn Sie versuchen, eine setattr auf ein eingebautes Objekt.

Aktualisierung: Aus dem Kommentar ist dies eine Wiederholung von: Warum kann man in Python keine Attribute zu einem Objekt hinzufügen?

1voto

Pjl Punkte 1704

Ich denke, der einfachste Weg ist über das Modul Sammlungen.

import collections
FinanceCtaCteM = collections.namedtuple('FinanceCtaCte', 'forma_pago doc_pago get_total')
def get_total(): return 98989898
financtacteobj = FinanceCtaCteM(forma_pago='CONTADO', doc_pago='EFECTIVO',
                                get_total=get_total)

print financtacteobj.get_total()
print financtacteobj.forma_pago
print financtacteobj.doc_pago

1voto

Weilory Punkte 1697

Wenn Sie für die Kette Zuordnung suchen, um Dinge wie django Modell Vorlage abstrakte Attribut zuweisen zu tun:

from types import SimpleNamespace

def assign(target, *args, suffix):
    ls = target
    for i in range(len(args) - 1):
        a = args[i]
        ns = SimpleNamespace()
        setattr(ls, a, ns)
        ls = ns
    setattr(ls, args[-1], suffix)
    return ls

a = SimpleNamespace()
assign(a, 'a', 'b', 'c', suffix={'name': 'james'})
print(a.a.b.c)
# {'name': 'james'}

die es Ihnen erlaubt, model als eine target und weisen Sie ihm das Attribut end zu.

0voto

Paul Whipp Punkte 14811

Kommen zu diesem spät in den Tag, aber hier ist mein pennyworth mit einem Objekt, das gerade geschieht, um einige nützliche Pfade in einer app zu halten, aber Sie können es für alles anpassen, wo Sie eine Art Diktat von Informationen, die Sie mit getattr und Punkt-Notation zugreifen können (was ich denke, diese Frage ist wirklich über):

import os

def x_path(path_name):
    return getattr(x_path, path_name)

x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
    setattr(x_path, name, os.path.join(x_path.root, name))

Das ist cool, denn jetzt:

In [1]: x_path.projects
Out[1]: '/home/x/projects'

In [2]: x_path('caches')
Out[2]: '/home/x/caches'

Dies verwendet also das Funktionsobjekt wie die obigen Antworten, aber verwendet die Funktion, um die Werte zu erhalten (Sie können immer noch verwenden (getattr, x_path, 'repository') statt x_path('repository') wenn Sie es vorziehen).

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