2009-05-28 10 views
6

Questo è un seguito alla domanda 912526 - How do I pass lots of variables to and from a function in Python?.Come utilizzare le classi derivate dalla classe list di Python

Ci sono molte variabili che devono essere passate nel programma che sto scrivendo, e dalla mia domanda precedente capisco che dovrei mettere queste variabili in classi e poi passare attorno alle classi.

Alcune di queste variabili sono disponibili in serie ripetitive. Per un calcolo a pellicola sottile è necessario tenere traccia delle proprietà ottiche (indice di rifrazione, assorbimento, spessore, ecc.) Per un numero di strati.

È il modo migliore per memorizzare variabili come questa per creare una classe derivata da un elenco Python per memorizzare l'insieme di classi che contengono ciascuna le variabili per un singolo livello? E poi inserire le funzioni che si occupano del set di layer in classe derivato dall'elenco e le funzioni che si occupano di un layer specifico in quella classe? C'è un modo migliore per farlo con una singola classe?

Utilizzando l'approccio a due di classe nel seguente esempio, sono in grado di impostare le cose in modo che io possa accedere alle variabili utilizzando statments come

n1 = layers[5].n 

Questo è il modo migliore per fare questo, giusto?

#Test passing values to and from functions 

class Layers(list): 

    def add(self,n,k,comment): 
     self.append(OneLayer(n,k,comment)) 

    def input_string(self): 
     input_string = [] 
     for layer in self: 
      vars = layer.input_string() 
      for var in vars: 
       input_string.append(var) 
     return input_string 

    def set_layers(self,results): 
     for layer,i in enumerate(self): 
      j = i*layer.num_var 
      layer.set_layer(*results[j:j+2]) 

class OneLayer(object): 

    def __init__(self,n,k,comment): 
     self.n = n 
     self.k = k 
     self.comment = comment 

    def input_string(self): 
     return [['f','Index of Refraction',self.n], ['f','Absorption',self.k],['s','Comment',self.comment]] 

    def set_layer(self,n,k,comment): 
     self.n = n; self.k=k; self.comment = comment 

    def num_var(self): 
     return 3 

if __name__ == '__main__': 
    layers = Layers() 

    layers.add(1.0,0.0,'This vacuum sucks') 
    layers.add(1.5,0.0,'BK 7 Glass') 

    print layers[0].n 
    print layers.input_string() 
    layers[1].set_layer(1.77,0.0,'Sapphire') 
    print layers.input_string() 

ottengo il seguente output di questo programma di test:

1.0 
[['f', 'Index of Refraction', 1.0], ['f', 'Absorption', 0.0], ['s', 'Comment', 'This vacuum sucks'], ['f', 'Index of Refraction', 1.5], ['f', 'Absorption', 0.0], ['s', 'Comment', 'BK 7 Glass']] 
[['f', 'Index of Refraction', 1.0], ['f', 'Absorption', 0.0], ['s', 'Comment', 'This vacuum sucks'], ['f', 'Index of Refraction', 1.77], ['f', 'Absorption', 0.0], ['s', 'Comment', 'Sapphire']] 
+1

Avete davvero bisogno di una classe 'Layers' che eredita da' list'? Basta usare invece una lista. –

risposta

9

Ci sono diversi problemi nel codice:

1.If effettuare qualsiasi operazione lista il risultato sarà un nativo lista:

layers1 = Layers() 
layers2 = Layers() 
layers1 + layers2 -> the result will be a native list 

2.Perché definire input_string quando si può ignorare __repr__ oppure __str__

3. Perché in questo caso è necessario derivare dall'elenco? Devi solo derivare dalla lista se vuoi che la tua classe si comporti esattamente come una lista. Ma nel tuo caso sembra che tu stia cercando un contenitore. Tutto quello che devi fare per ottenere la classe di comportarsi simile ad una lista è quello di sovrascrivere alcuni metodi di pitone speciali http://docs.python.org/reference/datamodel.html#emulating-container-types

class Layers(object): 
    def __init__(self, container=None): 
     if container is None: 
      container = [] 
     self.container = container 

    def add(self,n,k,comment): 
     self.container.append([n,k,comment]) 

    def __str__(self): 
     return str(self.container) 

    def __repr__(self): 
     return str(self.container) 

    def __getitem__(self, key): 
     return Layers(self.container[key]) 

    def __len__(self): 
     return len(self.container) 

>>> l = Layers() 
>>> l.add(1, 2, 'test') 
>>> l.add(1, 2, 'test') 
>>> l 
[[1, 2, 'test'], [1, 2, 'test']] 
>>> l[0] 
[1, 2, 'test'] 
>>> len(l) 
2 
+0

@hopatcong: è possibile risolvere il primo problema implementando il metodo __add__. Vedi http://docs.python.org/reference/datamodel.html#emulating-numeric-types. –

+0

Solo un'aggiunta qui, __repr__ è la sostituzione corretta per input_string. __str__ dovrebbe essere per una spiegazione informale/semplice - non una rappresentazione completa dell'oggetto. – monokrome

+1

E il tuo codice ha un problema: valore di default mutabile, vedi http://stackoverflow.com/q/1132941/13543 –

Problemi correlati