Erstellen eines leeren Objekts in Python

76

Gibt es Verknüpfungen zum Definieren eines leeren Objekts in Python oder müssen Sie immer eine Instanz einer benutzerdefinierten leeren Klasse erstellen?

Bearbeiten: Ich meine ein leeres Objekt, das zum Entenschreiben verwendet werden kann.

Lächelt
quelle

Antworten:

99

Sie können type verwenden, um eine neue Klasse im laufenden Betrieb zu erstellen und sie dann zu instanziieren. Wie so:

>>> t = type('test', (object,), {})()
>>> t
<__main__.test at 0xb615930c>

Die einzugebenden Argumente sind: Klassenname, ein Tupel von Basisklassen und das Wörterbuch des Objekts. Welche kann Funktionen (die Methoden des Objekts) oder Attribute enthalten.

Sie können die erste Zeile tatsächlich auf kürzen

>>> t = type('test', (), {})()
>>> t.__class__.__bases__
(object,)

Da der Typ standardmäßig neue Stilklassen erstellt, die vom Objekt erben.

typewird in Python für die Metaprogrammierung verwendet .

Aber wenn Sie nur eine Instanz eines Objekts erstellen möchten. Dann erstellen Sie einfach eine Instanz davon. Wie Lejlot vorschlägt.

Das Erstellen einer Instanz einer neuen Klasse wie dieser weist einen wichtigen Unterschied auf, der nützlich sein kann.

>>> a = object()
>>> a.whoops = 1
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'whoops'

Wohingegen:

>>> b = type('', (), {})()
>>> b.this_works = 'cool'
>>> 
Aychedee
quelle
73

Ja, in Python 3.3 wurde SimpleNamespace hinzugefügt

Im Gegensatz zu Objekten können Sie mit SimpleNamespace Attribute hinzufügen und entfernen. Wenn ein SimpleNamespace-Objekt mit Schlüsselwortargumenten initialisiert wird, werden diese direkt dem zugrunde liegenden Namespace hinzugefügt.

Beispiel:

import types

x = types.SimpleNamespace()
x.happy = True

print(x.happy) # True

del x.happy
print(x.happy) # AttributeError. object has no attribute 'happy'
Vlad Bezden
quelle
46

Eine einfache, weniger erschreckend aussehende Möglichkeit, ein leeres (-ish) Objekt zu erstellen, besteht darin, die Tatsache auszunutzen, dass Funktionen Objekte in Python sind, einschließlich Lambda-Funktionen:

obj = lambda: None
obj.test = "Hello, world!"

Zum Beispiel:

In [18]: x = lambda: None

In [19]: x.test = "Hello, world!"

In [20]: x.test
Out[20]: 'Hello, world!'
Wille
quelle
Ich mag diese Lösung, weil ich keinen Namen nennen muss
Hugh Perkins
3
Hmmm, aber es hat den Nachteil, den Sie nicht zuordnen könnenx.__class__.somefunc
Hugh Perkins
1
Diese Lösung hat ein Problem, wenn ich versuche, dieses Objekt zu kopieren. types.SimpleNamespace () in Python 3 ist eine bessere Lösung.
cn123h
12

Was meinst du mit "leeres Objekt"? Instanz des Unterrichts object? Sie können einfach laufen

a = object()

oder meinst du vielleicht initialisierung auf die null referenz? Dann können Sie verwenden

a = None
Lejlot
quelle
21
Ich frage mich, was das OP tun kann, wenn aes entweder als definiert ist object()oder Noneweil es in solchen Fällen akeinen Namespace hat __dict__und kein Attribut hinzugefügt werden kann a, um dies beispielsweise zu mögen a.x = 10.
Eyquem
1
In der Tat a = object(); a.foo = 'bar'gibt AttributeError: 'object' object has no attribute 'foo'.
Basj
3

Alle vorgeschlagenen Lösungen sind etwas umständlich.

Ich habe einen Weg gefunden, der nicht hackig ist, sondern dem ursprünglichen Design entspricht.

>>> from mock import Mock
>>> foo = Mock(spec=['foo'], foo='foo')
>>> foo.foo
'foo'
>>> foo.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../virtualenv/local/lib/python2.7/site-packages/mock/mock.py", line 698, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'bar'

Die Dokumentation von unittest.mock finden Sie hier.

qben
quelle
1

Erstellt ein neues leeres Set-Objekt . Wenn der optionale iterierbare Parameter angegeben wird, wird der Satz mit Elementen aktualisiert, die aus der Iteration erhalten wurden. Alle Elemente in iterable sollten unveränderlich sein oder unter Verwendung des im Abschnitt Protokoll für die automatische Konvertierung in unveränderlich beschriebenen Protokolls in ein unveränderliches umgewandelt werden können.

Ex:

myobj = set()
for i in range(1,10): myobj.add(i)
print(myobj)
D z
quelle
1

Sie haben es in der Frage gesagt, aber da keine Antwort es mit Code erwähnte, ist dies wahrscheinlich eine der saubersten Lösungen:

class Myobject:
    pass

x = Myobject()
x.test = "Hello, world!"  # working

Basj
quelle
1

Sie können verwenden

x = lambda: [p for p in x.__dict__.keys()]

Dann

x.p1 = 2
x.p2 = "Another property"

Nach

x()
# gives
# ['p1', 'p2']

Und

[(p, getattr(x,p)) for p in x()]
# gives
# [('p1', 2), ('p2', 'Another property')]
Brault Gilbert
quelle
0

Meiner Meinung nach ist der einfachste Weg:

def x():pass
x.test = 'Hello, world!'
Rastersoft
quelle