Como se mencionó anteriormente, si desea mantener las cosas simples, simplemente utilice un atributo por ejemplo _ordering
, que realiza un seguimiento manual de los pedidos. De lo contrario, aquí hay un enfoque de metaclase (como el que utiliza Django), que crea un atributo de ordenamiento de forma automática.
Registro de la orden original
Las clases no perder de vista el orden de los atributos. Sin embargo, puede realizar un seguimiento del orden en que se crearon las instancias de campo. Para eso, tendrás que usar tu propia clase para los campos (no int). La clase realiza un seguimiento de cuántas instancias se han realizado y cada instancia toma nota de su posición. Esta es la manera que lo haría por su ejemplo (enteros almacenamiento):
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
Creación de un atributo ordered_items
automáticamente
Ahora que sus campos tienen un número que puede ser utilizado para pedirlos, sus padres la clase necesita usar eso de alguna manera. Puedes hacer esto de varias maneras, si no recuerdo mal, Django usa Metaclasses para hacer esto, lo cual es un poco salvaje para una clase simple.
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
El uso de este metaclase
Así que, ¿cómo se utiliza esto? En primer lugar, debe usar nuestra nueva clase MyOrderedField
al definir sus atributos.Esta nueva clase se mantendrá un registro del orden en que se crearon los campos:
class Ordered(object):
__metaclass__ = BaseWithOrderedFields
x = MyOrderedField(0)
z = MyOrderedField(0)
b = MyOrderedField(0)
a = MyOrderedField(0)
A continuación, se puede acceder a los campos ordenados en nuestro atributo creado automáticamente ordered_fields
:
>>> ordered = Ordered()
>>> ordered.ordered_fields
[('x', 0), ('z', 0), ('b', 0), ('a', 0)]
dude en cambiar esto a un dict ordenado o simplemente devuelva los nombres o lo que sea que necesite. Además, puede definir una clase vacía con el __metaclass__
y heredar desde allí.
¡No lo use!
Como puede ver, este enfoque es un poco complicado y probablemente no adecuado para la mayoría de las tareas o desarrolladores de Python. Si eres nuevo en Python, probablemente gastarás más tiempo y esfuerzo en desarrollar tu metaclase de lo que lo hubieras hecho si hubieras definido el orden de forma manual. Definir su propio pedido de forma manual casi siempre será el mejor enfoque. Django lo hace automáticamente porque el código complicado está oculto para el desarrollador final, y Django se usa mucho más a menudo de lo que se escribe/mantiene. Entonces, solo si está desarrollando un marco para otros desarrolladores, entonces las metaclases pueden ser útiles para usted.
métodos, propiedades, etc se almacenan como objetos dentro de los diccionarios, y los diccionarios son, por definición, no ordenada. ¿Qué estás tratando de lograr (o mejor, por qué)? –
Necesita Python 3 para hacer esto sin hacks: http://stackoverflow.com/a/4460565/821378 –