Wie bereits erwähnt, können Sie, wenn Sie es einfach halten wollen, einfach ein eg verwenden. _ordering
Attribut, das die Reihenfolge manuell festlegt. Andernfalls ist hier ein Metaklassen-Ansatz (wie der, den Django verwendet), der ein Ordnungsattribut automatisch erstellt.
Aufzeichnung der ursprünglichen Bestellung
Die Klassen behalten die Reihenfolge der Attribute nicht im Auge. Sie können jedoch verfolgen, in welcher Reihenfolge die Feldinstanzen erstellt wurden. Dazu müssen Sie eine eigene Klasse für Felder (nicht int) verwenden. Die Klasse merkt sich, wie viele Instanzen bereits erstellt wurden, und jede Instanz merkt sich ihre Position. So würden Sie es für Ihr Beispiel (Speicherung von Integern) machen:
class MyOrderedField(int):
creation_counter = 0
def __init__(self, val):
# Set the instance's counter, to keep track of ordering
self.creation_counter = MyOrderedField.creation_counter
# Increment the class's counter for future instances
MyOrderedField.creation_counter += 1
Erstellen einer ordered_items
Attribut automatisch
Nun, da Ihre Felder eine Nummer haben, die verwendet werden kann, um sie zu ordnen, muss Ihre übergeordnete Klasse das irgendwie verwenden. Sie können dies auf verschiedene Arten tun. Wenn ich mich richtig erinnere, verwendet Django dazu Metaklassen, was für eine einfache Klasse ein bisschen wild ist.
class BaseWithOrderedFields(type):
""" Metaclass, which provides an attribute "ordered_fields", being an ordered
list of class attributes that have a "creation_counter" attribute. """
def __new__(cls, name, bases, attrs):
new_class = super(BaseWithOrderedFields, cls).__new__(cls, name, bases, attrs)
# Add an attribute to access ordered, orderable fields
new_class._ordered_items = [(name, attrs.pop(name)) for name, obj in attrs.items()
if hasattr(obj, "creation_counter")]
new_class._ordered_items.sort(key=lambda item: item[1].creation_counter)
return new_class
Verwendung dieser Metaklasse
Und wie benutzt man das? Zunächst müssen Sie unsere neue MyOrderedField
Klasse, wenn Sie Ihre Attribute definieren. Diese neue Klasse merkt sich die Reihenfolge, in der die Felder erstellt wurden:
class Ordered(object):
__metaclass__ = BaseWithOrderedFields
x = MyOrderedField(0)
z = MyOrderedField(0)
b = MyOrderedField(0)
a = MyOrderedField(0)
Dann können Sie auf die bestellten Felder in unserem automatisch erstellten Attribut ordered_fields
:
>>> ordered = Ordered()
>>> ordered.ordered_fields
[('x', 0), ('z', 0), ('b', 0), ('a', 0)]
Es steht Ihnen frei, dies in ein geordnetes Diktat zu ändern oder nur die Namen zurückzugeben oder was immer Sie benötigen. Zusätzlich können Sie eine leere Klasse mit der Option __metaclass__
und erben von dort.
Benutzen Sie das nicht!
Wie Sie sehen können, ist dieser Ansatz ein wenig zu kompliziert und wahrscheinlich nicht für die meisten Aufgaben oder Python-Entwickler geeignet. Wenn Sie ein Python-Neuling sind, werden Sie wahrscheinlich mehr Zeit und Mühe aufwenden, um Ihre Metaklasse zu entwickeln, als wenn Sie die Reihenfolge einfach manuell definiert hätten. Es ist fast immer die beste Lösung, die Reihenfolge manuell zu definieren. Django macht das automatisch, weil der komplizierte Code vor dem Endentwickler verborgen ist und Django viel öfter benutzt wird, als es selbst geschrieben/gewartet wird. Nur wenn Sie also ein Framework für andere Entwickler entwickeln, können Metaklassen für Sie nützlich sein.
1 Stimmen
Methoden, Eigenschaften usw. werden als Wörterbücher in Objekten gespeichert, und Wörterbücher sind per Definition ungeordnet. Was wollen Sie erreichen (oder besser, warum)?
0 Stimmen
Sie benötigen Python 3, um dies ohne Hacks zu tun: stackoverflow.com/a/4460565/821378