2009-05-28 23 views
6

Este es un seguimiento de la pregunta 912526 - How do I pass lots of variables to and from a function in Python?.Cómo utilizar las clases derivadas de la clase de lista de Python

Hay muchas variables que deben pasarse por alto en el programa que estoy escribiendo, y de mi pregunta anterior entiendo que debería poner estas variables en clases, y luego pasar las clases.

Algunas de estas variables vienen en conjuntos repetitivos: para un cálculo de película delgada, necesito rastrear las propiedades ópticas (índice de refracción, absorción, espesor, etc.) para varias capas.

¿Es la mejor manera de almacenar variables como esta crear una clase derivada de una lista de Python para almacenar el conjunto de clases que cada una contiene las variables para una sola capa? Y luego ponga las funciones que se ocupan del conjunto de capas en la clase derivadas de la lista, y las funciones que se ocupan de una capa específica en esa clase? ¿Hay una mejor manera de hacer esto con una sola clase?

Utilizando el enfoque de dos clases en el siguiente ejemplo, que soy capaz de preparar las cosas para que pueda acceder a las variables utilizando statments como

n1 = layers[5].n 

Ésta es la mejor manera de hacer esto, ¿verdad?

#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() 

tengo la siguiente salida de este programa de prueba:

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

¿Usted realmente necesita una clase 'Layers' que hereda de' list'? Solo use una lista en su lugar. –

Respuesta

9

Hay varios problemas en su código:

1. Si usted hace cualquier operación de la lista el resultado será un nativo lista:

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

2.Why definir input_string cuando se puede anular __repr__ o __str__

3.¿Por qué incluso tiene que derivar de la lista en este caso? Solo necesita derivar de la lista si desea que su clase se comporte exactamente como una lista. Pero en tu caso parece que estás buscando un contenedor. Todo lo que necesita hacer para obtener la clase de comportamiento más parecido a una lista es para anular algunos métodos especiales pitón 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: Puede solucionar el primer problema implementando el método __add__. Ver http://docs.python.org/reference/datamodel.html#emulating-numeric-types. –

+0

Solo una adición aquí, __repr__ es el reemplazo apropiado para input_string. __str__ se supone que es para una explicación informal/simple, no una representación completa del objeto. – monokrome

+1

Y su código tiene un problema: valor predeterminado mutable, vea http://stackoverflow.com/q/1132941/13543 –

Cuestiones relacionadas