What is the most efficient way to format code output to the user?

Asked

Viewed 108 times

3

What is the most efficient way to format the output of my code? It is a classic exercise of the internet, but I would like to improve it.

I want to leave the bars of "limit", (|) always with the same pattern, but when executing the code, depending on the result they distort as in the image below.

inserir a descrição da imagem aqui

from os import system

def calculo():
  peso_peixe = float(input('Informe o peso do peixe (em Kgs): '))
  if peso_peixe > 50:
    excesso = peso_peixe - 50
    print('|---------------------------------------------------------|')
    print('|                                                         |')
    print('|Peso do peixe exedeu o limite de 50kgs em {:.2f} Kgs      |'.format(excesso))
    print('|                                                         |')
    print('|O valor da Multa é R$ 4,00 por Kg exedido                |')
    print('|                                                         |')
    multa = excesso * 4.0
    print('|Deverá ser pago uma multa de R${:.2f}                    |'.format(multa))
    print('|---------------------------------------------------------|')
  else:
    print('|--------------------------------------------------------------|')
    print('|                                                              |')
    print('|O peso informado para o peixe é {:.2f} Kgs, não gerando multa! |'.format(peso_peixe))
    print('|                                                              |')
    print('|--------------------------------------------------------------|')
    

calculo()

while True:
  continuar = str(input('\nDESEJA EXECUTAR NOVAMENTE? (S/N) ')).upper()
  system('cls||clear')
  if continuar != 'S':
    break
  calculo()

1 answer

8


The string formatting mini-language used by "format" by the f-strings allows you to specify the output width of any string, and how to complete the missing spaces.

So if I want any number to be exactly 7 characters wide, filled by spaces, I can do:

In [51]: print("|{:7.2f}|\n|{:7.04f}|".format(2.34567, 2.34567))                                          
|   2.35|
| 2.3457|

The complete documentation is here: https://docs.python.org/3/library/string.html#format-Specification-mini-language (and is not the easiest to read documentation in the world, sorry)

With this you could control the widths of the numbers in your example, and make the bars aligned - but it’s far from being the best way to do that. Suddenly it is even the most "efficient" depends on the criterion you use for "efficient" (it may be the fastest to run by a factor of close to 0.5%, for example).

thinking modularly

But that implies that All your program, in each output you are going to do for the user, you will have to keep counting the sizes and adjusting the formatting. You already have to do this above.

The best thing is you create a function that "embellish" the output as you like, and simply passes a list of strings to it. Then you leave the computer do the math of how much space needs to be added before and after each line of text to place the frames for you.

This, in addition to making your life much easier, allows you to only worry about generating results in the "core" of your program - and elsewhere, you worry about presentation - is the same principle used more than 20 years ago when they decided that the presentation of web pages would be controlled by CSS - a language completely different from HTML, which only cares about saying "what is what".

Without doing anything too sophisticated - just a function that allows you to draw frames like the one you already draw, the code can look like this:

def imprime_formatado(texto, largura=60, moldura="|_+"):
    vertical, horizontal, canto = moldura
    print(f"{canto}{horizontal * (largura - 2)}{canto}")
    
    # cria uma copia da lista de strings, para não alterar a original, e acrescenta
    # uma linha em branco no começo e uma no final, para espaçamento:
    
    texto = texto[:]
    texto.insert(0, '')
    texto.append('')
    for linha in texto:
        print (f"{vertical}{linha:{largura-2}s}{vertical}")
    print(f"{canto}{horizontal * (largura - 2)}{canto}")
    

def calculo():
    peso_peixe = float(input('Informe o peso do peixe (em Kgs): '))
    if peso_peixe > 50:
        excesso = peso_peixe - 50
        multa = excesso * 4.0
        texto = [
            f'|Peso do peixe exedeu o limite de 50kgs em {excesso:.2f} Kgs',
            '',
            'O valor da Multa é R$ 4,00 por Kg excedido',
            '',
            f'Deverá ser pago uma multa de R${multa:.2f}',
        ]
    else:
        texto = [f'O peso informado para o peixe é {peso_peixe:.2f} Kgs, não gerando multa!']
    
    imprime_formatado(texto)

Note that even in such a simple function, it is easy to change the frame - if I want a message with a mold with "*" instead of "|_+" just call with moldura="***" - and you can sophisticate much more, without hinting at the logic that is the "nucleus" of your program: the calculation of the fine, etc...

In time: I changed the calls to the "format" method to use "f-strings" - you put the prefix "f" and you can directly put Python expressions inside the { } string, including variables- this is much easier and easier to use than calling ". format", which in gera will only appear in documentation and books written before the "3.6" version of Python exists or is more widespread.

  • Brilliant answer. Just do not vote again pq already voted. There is a module ready for this in python?

  • 1

    has something - but there is no language "guess" how much each will want to decorate the output of a simple program to the terminal. The "textwrap" module of the standard library has some functionality to format text like this. But in general, if a program gets more serious, it will have a graphical interface, or a web interface - and the text formatting features come along with the framework used for the interface.

  • 1

    To print frames in the terminal, has the "curses" that does not work in Windows, or you can build an interface using a project like "terminedia" or "python prompt Toolkit"

Browser other questions tagged

You are not signed in. Login or sign up in order to post.