Pergunta

Eu faço programação científica, e muitas vezes quer mostrar usuários prompts e pares de variáveis, que eles editar as variáveis, e depois fazer as calulations com as novas variáveis. Eu faço isso tantas vezes, que eu escrevi uma classe wxPython para mover este código fora do programa principal. Você configurar uma lista para cada variável com o tipo da variável (string, float, int), o prompt, e o valor atual da variável. Você, então, colocar todas estas listas em uma lista grande, e meu utilitário cria um painel wxPython ordenadamente formatado com prompts e os valores atuais que podem ser editados.

Quando eu comecei, eu tinha apenas algumas variáveis, por isso gostaria de escrever cada variável.

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

Agora eu quero usar essa rotina para uma série de variáveis ??(10-30), e esta abordagem é quebrar. Eu posso criar a lista de entrada para a função em várias linhas usando o list.append () declarações. Quando o código de retorno da função, porém, eu recebo essa lista enorme que precisa ser descompactado para as variáveis ??certas. Isto é difícil de gerir, e parece que ele vai ser fácil para obter a lista de entrada e lista de saída fora de sincronia. E pior do que isso, parece kludgy.

Qual é a melhor maneira de passar muitas variáveis ??para uma função em Python com informações adicionais para que possam ser editadas, e então obter as variáveis ??de volta para que eu possa usá-los no resto do programa?

Se eu pudesse passar as variáveis ??por referência para a função, em seguida, os usuários podem alterá-los ou não, e eu gostaria de usar os valores uma vez que o programa retornado da função. Eu só precisaria construir a lista de entrada em várias linhas, e não haveria qualquer possibilidade da lista de entrada ficando fora de sincronia com a lista de saída. Mas Python não permite isso.

Eu deveria quebrar as grandes listas em listas menores que, em seguida, se combinados em listas grandes para passar para dentro e fora das funções? Ou será que isso só adicionar mais lugares para fazer erros?

Foi útil?

Solução

A coisa mais simples a fazer seria criar uma classe. Em vez de lidar com uma lista de variáveis, a classe terá atributos. Então você acabou de usar uma única instância da classe.

Outras dicas

Existem duas opções decentes que vêm à mente.

A primeira é usar um dicionário para reunir todas as variáveis ??em um só lugar:

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

A segunda é usar uma classe para agrupar todos os argumentos. Isso poderia ser algo tão simples como:

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

Neste caso, eu preferiria a classe sobre o dicionário, simplesmente porque você poderia eventualmente fornecer uma definição para a classe para tornar a sua utilização mais clara ou para fornecer métodos que lidar com algumas das embalagens e trabalho de descompactação.

Para mim, a solução ideal é usar uma classe como este:

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

Você também pode construir um dicionário e passá-lo como este:

>>> 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

Você pode, então, obter dados ou alterá-lo sempre que necessário quando passá-la para uma função:

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

Se eu pudesse passar as variáveis ??por referência para a função, em seguida, os usuários podem alterá-los ou não, e eu gostaria de usar os valores uma vez que o programa retornado da função.

Você pode obter o mesmo efeito como "passar por referência", passando um dict (ou por conveniência sintática um Bunch, consulte http://code.activestate.com/recipes/52308/ ).

Se você tem um conjunto finito destes casos, você poderia escrever funções de mensagens publicitárias específicas para cada um. Cada embalagem faria o trabalho de construção e descompactar listas taht são passados ??para a função interna.

  1. eu recomendo usar um dicionário ou uma classe para acumular todos os detalhes sobre suas variáveis
    • valor
    • texto de aviso
  2. A lista para armazenar a ordem em que você deseja que eles sejam exibidos
  3. Em seguida, use o bom iteração de idade para preparar a entrada e saída coleta

Desta forma, você só vai estar modificando uma pequena seção administrável do tempo de código e de novo. Claro que você deve encapsular tudo isso em uma classe se o seu trabalho confortável com classes.

"""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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top