Pregunta

hago programación científica, ya menudo quiero mostrar a los usuarios indicaciones y los pares de variables, dejarlos editar las variables, y luego hacer que los cálculos con las nuevas variables. Lo hago tan a menudo, que escribí una clase wxPython para mover el código del programa principal. Se configura una lista para cada variable con el tipo de la variable (cadena, flotador, int), el símbolo y el valor actual de la variable. A continuación, coloque todas estas listas en una enorme lista, y mi utilidad crea un panel wxPython perfectamente formateado con indicaciones y los valores actuales que se pueden editar.

Cuando empecé, sólo tenía unas pocas variables, por lo que iba a escribir a cabo cada variable.

s='this is a string'; i=1; f=3.14
my_list=[ ['s','your string here',s], ['i','your int here',i], ['f','your float here'],]
input_panel = Input(my_list)

 # the rest of the window is created, the input_panel is added to the window, the user is
 # allowed to make  choices, and control returns when the user hits the calculate button

s,i,f = input_panel.results()     # the .results() function returns the values in a list

Ahora quiero utilizar esta rutina para una gran cantidad de variables (10-30), y este enfoque se está rompiendo. Puedo crear la lista de entrada a la función a través de múltiples líneas utilizando el list.append) (declaraciones. Cuando el código devuelve desde la función, sin embargo, tengo este enorme lista que necesita ser desempaquetado en las variables correctas. Esto es difícil de manejar, y que parece que va a ser fácil conseguir la lista de entrada y salida de la lista fuera de sincronía. Y peor que eso, parece kludgy.

¿Cuál es la mejor manera de pasar una gran cantidad de variables a una función en Python con información extra para que puedan ser editadas, y luego obtener las variables de vuelta para que pueda usarlos en el resto del programa?

Si pudiera pasar las variables por referencia en la función, los usuarios pueden cambiar o no, y me gustaría utilizar los valores una vez que el programa de regresar de la función. Yo sólo necesito para construir la lista de entrada a través de múltiples líneas, y no habría ninguna posibilidad de conseguir la lista de entrada fuera de sincronía con la lista de salida. Pero Python no permite esto.

¿Debo romper las listas grandes en listas más pequeñas que luego son combinadas en grandes listas para pasar dentro y fuera de las funciones? ¿O es que esto sólo añadir más lugares para hacer errores?

¿Fue útil?

Solución

Lo más sencillo que hacer sería la creación de una clase. En lugar de tratar con una lista de variables, la clase tendrá atributos. Entonces sólo tiene que utilizar una única instancia de la clase.

Otros consejos

Hay dos opciones decentes que vienen a la mente.

La primera es usar un diccionario para reunir todas las variables en un solo lugar:

d = {}
d['var1'] = [1,2,3]
d['var2'] = 'asdf'
foo(d)

El segundo es el uso de una clase para agrupar todos los argumentos. Esto podría ser algo tan simple como:

class Foo(object):
    pass
f = Foo()
f.var1 = [1,2,3]
f.var2 = 'asdf'
foo(f)

En este caso, yo preferiría la clase sobre el diccionario, simplemente porque con el tiempo podría proporcionar una definición de la clase para hacer su uso más claro o para proporcionar métodos que manejan algunos de los trabajos de embalaje y desembalaje.

Para mí, la solución ideal es utilizar una clase como esta:

>>> class Vars(object):
...     def __init__(self, **argd):
...             self.__dict__.update(argd)
...
>>> x = Vars(x=1, y=2)
>>> x.x
1
>>> x.y
2

También es posible construir un diccionario y pasarlo como esto:

>>> some_dict = {'x' : 1, 'y' : 2}
>>> #the two stars below mean to pass the dict as keyword arguments
>>> x = Vars(**some_dict)  
>>> x.x
1
>>> x.y
2

A continuación, puede obtener datos o alterar como se da el caso cuando se pasa a una función:

>>> def foo(some_vars):
...     some_vars.z = 3 #note that we're creating the member z
...
>>> foo(x)
>>> x.z
3
  

Si pudiera pasar las variables por referencia en la función, los usuarios pueden cambiar o no, y me gustaría utilizar los valores una vez que el programa devuelve desde la función.

Puede obtener el mismo efecto como "pasar por referencia" haciendo pasar una dict (o por conveniencia sintáctica un Bunch, ver http://code.activestate.com/recipes/52308/ ).

Si usted tiene un conjunto finito de estos casos, se podría escribir funciones de contenedor específico para cada uno. Cada envoltorio haría el trabajo de la construcción y desembalaje listas taht se pasan a la función interna.

  1. Yo recomiendo usar un diccionario o una clase de acumular todos los detalles sobre las variables
    • valor
    • texto del mensaje
  2. Una lista para guardar el orden en el que desea que se muestren
  3. A continuación, utilice buena iteración de edad para preparar entrada y recoger salida

De esta manera sólo se le modificando una pequeña sección manejable del código de tiempo y otra vez. Por supuesto debe encapsular todo esto en una clase si su cómoda utilización de clases.

"""Store all variables
"""
vars = {}
"""Store the order of display
"""
order = []

"""Define a function that will store details and order of the variable definitions
"""
def makeVar(parent, order, name, value, prompt):
    parent[name] = dict(zip(('value', 'prompt'), (value, prompt)))
    order.append(name)

"""Create your variable definitions in order
"""
makeVar(vars, order, 's', 'this is a string', 'your string here')
makeVar(vars, order, 'i', 1, 'your int here')
makeVar(vars, order, 'f', 3.14, 'your float here')

"""Use a list comprehension to prepare your input
"""
my_list = [[name, vars[name]['prompt'], vars[name]['value']] for name in order]
input_panel = Input(my_list)

out_list = input_panel.results();
"""Collect your output
"""
for i in range(0, len(order)):
    vars[order[i]]['value'] = out_list[i];
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top