2010-02-17 18 views
9

Python viene fornito con la pratica funzione dir() che dovrebbe elencare il contenuto di una classe per te. Ad esempio, per questa classe:Come eseguire iterazioni sugli attributi di una classe, nell'ordine in cui sono stati definiti?

class C: 
    i = 1 
    a = 'b' 

dir(C) sarebbe tornare

['__doc__', '__module__', 'a', 'i'] 

Questo è grande, a meno di notare come l'ordine di 'a' e 'i' ora è diverso quindi nell'ordine in cui sono stati definiti in

.

In che modo è possibile scorrere gli attributi di C (potenzialmente ignorando gli attributi del modulo integrato & nell'ordine in cui sono stati definiti? Per la classe C sopra, il valore sarebbe 'i' quindi 'a'.

Addendum: - Sto lavorando su qualche serializzazione/codice di registrazione in cui voglio serializzare gli attributi nell'ordine in cui sono stati definiti in modo che l'output sia simile al codice che ha creato la classe.

+0

Perché l'ordine in cui sono definiti è importante? L'ordine è irrilevante in questo caso. Come useresti queste informazioni se potessi averlo? –

+0

Stai serializzando la classe o le istanze della classe? Nel tuo esempio, 'a' e' i' sono attributi di classe. Se vuoi dire che questi sono attributi di istanza, dovresti definirli in '__init__' usando' self.a = 'b'' e 'self.i = 1'. – PaulMcG

+0

Questi sono attributi di livello di classe, che non sono così utili come le variabili di istanza. Perché stai cercando di mantenere l'ordine degli attributi di classe? Non sarebbe meglio preservare l'ordine delle variabili di istanza?Perché stai provando a fare trucchi con le variabili a livello di classe? –

risposta

7

Non penso sia possibile in Python 2.x. Quando i membri della classe vengono forniti al metodo __new__, vengono forniti come dizionario, quindi l'ordine è già stato perso in quel punto. Pertanto anche i metaclassi non possono aiutarti (a meno che non ci siano funzionalità aggiuntive che mi sono sfuggite).

In Python 3 è possibile utilizzare il nuovo metodo speciale __prepare__ per creare un dettato ordinato (questo è anche indicato come esempio in PEP 3115).

+0

Ecco come lo fa Django (Python 2.xe versioni successive): https://github.com/django/django/blob/stable/1.3.x/django/db/models/fields/__init__.py#L56 – tobych

+0

Non ho ancora usato Django, ma suppongo che ciò richieda che in ogni incarico creiamo una nuova istanza di 'Field'? Sembra una buona soluzione. – nikow

+0

Sì, è quello che fa Django. – tobych

1

Questa informazione non è accessibile, poiché gli attributi sono memorizzati in un dict, che è intrinsecamente non ordinato. Python non memorizza queste informazioni sull'ordine ovunque.

Se si desidera che il formato di serializzazione per memorizzare le cose in un certo ordine che ci si specificare che ordine esplicito. Non useresti dir, che contiene cose che non conosci o che ti interessano, forniresti esplicitamente una lista (o qualsiasi altra cosa) che descrive cosa serializzare.

2

Sono nuovo in python, quindi la mia soluzione potrebbe non essere efficace

class Q: 
def __init__(self): 
    self.a = 5 
    self.b = 10 

if __name__ == "__main__": 
    w = Q() 
    keys = w.__dict__.keys() 
    for k in keys: 
     print "Q.%s = %d"%(k,w.__dict__[k]) 

uscita è:

Q.a = 5 
Q.b = 10 
+0

Ciò non mantiene l'ordine. –

2

mettere questo metodo nella classe

def __setattr__(self, attr, value): 
    if attr not in dir(self): 
     if attr == "__ordered_fields__": 
      super.__setattr__(self, attr, value) 
     else: 
      if not hasattr(self, "__ordered_fields__"): 
       setattr(self, "__ordered_fields__", []) 
      self.__ordered_fields__.append(attr) 
      super.__setattr__(self, attr, value) 

ea ottenere i campi in ordine, basta fare qualcosa come:

print(self.__ordered_fields__) 
Problemi correlati