He escrito una función que tendrá hasta 72 instrucciones IF y esperaba escribir código que será mucho más corto, pero no tengo idea de por dónde empezar

La función lee la variable self.timeselect cuando se selecciona un botón de opción y el resultado se guarda en un archivo de texto llamado missing_time.txt. Si el resultado es igual a 1, guarde "0000" en el archivo, si el resultado es 2, guarde 0020 en el archivo de texto, etc. Esto puede ser para 72 combinaciones posibles.

¿Hay alguna forma más inteligente de simplificar la función?

def buttonaction():
    selectedchoice = ""            
    if self.timeselect.get() == 1:                
        selectedchoice = "0000"
        orig_stdout = sys.stdout
        f = open('missing_time.txt', 'w')
        sys.stdout = f
        print(selectedchoice)
        f.close()
    if self.timeselect.get() == 2:                
        selectedchoice = "0020"
        orig_stdout = sys.stdout
        f = open('missing_time.txt', 'w')
        sys.stdout = f
        print(selectedchoice)
        f.close()

self.timeselect = tkinter.IntVar()

self.Radio_1 = tkinter.Radiobutton(text="0000",variable = 
self.timeselect,indicator = 0 ,value=1)  
self.Radio_1.place(x=50,y=200)
self.Radio_2 = tkinter.Radiobutton(text="0020",variable = 
self.timeselect,indicator = 0 ,value=2)  
self.Radio_2.place(x=90,y=200)
1
John 15 sep. 2018 a las 10:36

4 respuestas

La mejor respuesta
choice_map = {
    1 : "0000",
    2 : "0020"
}

def buttonaction():
    selected = self.timeselect.get()        
    if 0 < selected < 73:  # This works as intended in Python
        selectedchoice = choice_map[selected]
        # Do you intend to append to file instead of replacing it? 
        # See text below.
        with open("missing_time.txt", 'w') as outfile:
            outfile.write(selectedchoice + "\n")
            print(selectedchoice)

Mejor aún, si hay un patrón que relaciona el valor de self.timeselect.get() con la cadena que escribe, genere selectchoice directamente desde ese patrón en lugar de usar un diccionario para hacer el mapeo.

Editar

Me resulta un poco extraño que esté borrando el archivo "missing_time.txt" cada vez que llame a buttonaction. Si su intención es agregarlo, cambie el modo de archivo en consecuencia.

Además, en lugar de abrir y cerrar el archivo cada vez, es posible que solo desee abrirlo una vez y pasar el controlador a buttonaction o mantenerlo como global, dependiendo de cómo lo use.

Finalmente, si no tiene la intención de detectar KeyError de una clave inválida, puede hacer lo que @Clifford sugiere y usar choice_map.get(selected, "some default value that does not have to be str").

6
lightalchemist 15 sep. 2018 a las 10:46

Todo lo que necesita hacer en este caso es construir una cadena a partir del valor entero self.timeselect.get().

selectedchoice = self.timeselect.get()
if 0 < selectedchoice < 73:
    orig_stdout = sys.stdout
    f = open('missing_time.txt', 'w')
    sys.stdout = f
    print( str(selectedchoice).zfill(4) )     # Convert choice to 
                                              # string with leading
                                              # zeros to 4 charaters
    f.close()

Además, en aras de la simplificación, la redirección de stdout y su restauración es un método engorroso de salida a un archivo. En cambio, puede escribir directamente en el archivo:

    with open('missing_time.txt', 'w') as f:
        f.write(selectedchoice + "\n")

Tenga en cuenta que debido a que usamos el administrador de contexto with aquí, f se cierra automáticamente cuando abandonamos este contexto, por lo que no es necesario llamar a f.close(). Finalmente terminas con:

selectedchoice = self.timeselect.get()
if 0 < selectedchoice < 73:
    with open('missing_time.txt', 'w') as f:
        f.write( str(selectedchoice).zfill(4) + "\n" )

Incluso si utilizó los condicionales, cada uno difiere solo en la primera línea, por lo que solo esa parte debe ser condicional y el resto del contenido realizado después de los condicionales. Además, todos los condicionales son mutuamente exclusivos, por lo que puede usar else-if:

    if self.timeselect.get() == 1:                
        selectedchoice = "0000"

    elif self.timeselect.get() == 2:                
        selectedchoice = "0020"

    ...

    if 0 < selectedchoice < 73:
        with open('missing_time.txt', 'w') as f:
            f.write(selectedchoice + "\n")

En circunstancias donde no existe una relación aritmética directa entre selectchoice y la cadena requerida, o las opciones disponibles tal vez no son contiguas, es posible implementar un switch usando un diccionario:

choiceToString = {
    1:  "0001",
    2:  "0002",
    ...
    72: "0072",
}

selectedchoice = choiceToString.get( self.timeselect.get(), "Invalid Choice")

if selectedchoice != "Invalid Choice":
    with open('missing_time.txt', 'w') as f:
        f.write(selectedchoice + "\n")
3
lightalchemist 15 sep. 2018 a las 10:43

Como no hay una declaración de cambio en Python, realmente no puede reducir el número de declaraciones if. Pero veo dos formas de optimizar y reducir la longitud de su código.

Primero, puedes usar algunos

if condition:

elif condition:

En lugar de

if condition:

if condition:

Ya que no puede tener self.timeselect.get () evaluado en más de un int. En segundo lugar, puede envolver todo el código que no varía en una función. Puede deshacerse de la elección seleccionada y poner

orig_stdout = sys.stdout
f = open('missing_time.txt', 'w')
sys.stdout = f
print(selectedchoice)
f.close()

En una función writeToFile (selectedOption)

0
Paragoumba 15 sep. 2018 a las 07:50

Supongo que los valores son arbitrarios y no hay un patrón definido. También veo que lo único que cambia en su código es la variable SelectedChoice. Puede utilizar un Diccionario en tales casos. Los elementos de un diccionario son pares clave / valor para que pueda hacer referencia a la clave y obtener el valor.

dictionary = {
    1:"0000",
    2:"0020",
    3:"0300",
    4:"4000"
}

def buttonAction():
    selectedChoice = dictionary[self.timeselect.get()]
    if 0<selectedChoice<=72:
        f=open('missing_time.txt','w')
        f.write(selectedChoice+" ")
        f.close()
        print(choice)
0
Deeparth Gupta 15 sep. 2018 a las 08:37