8
\$\begingroup\$

I am starting to learn python and this has been my first project but I am not entirely happy, I think it could be done better. Could you help me? The strings are in Spanish but I think it does not harm understanding.

    elegir_magnitud = int(input(
"""1 = Temperatura
2 = Longitud 
3 = Masa
4 = Volumen
5 = Tiempo
6 = Divisa
Entra número deseado: """))
if elegir_magnitud == 1 :
    unidad_temperatura = int(input(
        """         

------------------Elige la unidad de temperatura a ser convertida:---------------
1 = Celsius
2 = Farhengei o como se escriba
3 = Kelvin
Entra número deseado: """))
    cantidad_temperatura = float(input(
        """

Entra la cántidad de esa unidad deseada: """))
#ELEGIR UNIDAD DE TEMPERATURA A CONVERTIR
    unidad_a_convertir = int(input(
        """         

--------------------Elige la unidad de temperatura a convertir:-----------------
1 = Celsius
2 = Farhengei o como se escriba
3 = Kelvin
Entra número deseado: """))
    if unidad_temperatura == unidad_a_convertir:
        print("Por qué quieres convertir a la misma unidad?")
    if unidad_temperatura == 1 and unidad_a_convertir == 3:
        print("""El resultado de la conversion es: \n""",float(cantidad_temperatura - 273),"ºK")
    if unidad_temperatura == 1 and unidad_a_convertir == 2:
        print("""El resultado de la conversion es: \n""",float(cantidad_temperatura * 9%5 +32),"ºF")
    if unidad_temperatura == 3 and unidad_a_convertir == 1:
        print("""El resultado de la conversion es: \n""",float(cantidad_temperatura + 273),"ºC")
    if unidad_temperatura == 3 and unidad_a_convertir == 2:
        print("""El resultado de la conversion es: \n""",float((cantidad_temperatura -273) * 9 % 5 + 32),"ºF")
    if unidad_temperatura == 2 and unidad_a_convertir == 3:
        print("""El resultado de la conversion es: \n""",float((cantidad_temperatura - 32) % 9 * 5 - 273),"ºK")
    if unidad_temperatura == 2 and unidad_a_convertir == 1:
        print("""El resultado de la conversion es: \n""",float(cantidad_temperatura % 9*5 -32),"ºC")
\$\endgroup\$
12
\$\begingroup\$

Localisation

The strings are in Spanish

Great! However, that's not the only thing in Spanish: your variables (elegir_magnitud, unidad_temperatura, etc.) are as well.

This is non-ideal for at least a couple of reasons:

  • Python, being a language whose syntax is written in English, conflicts with your code that is then a mixture of English and Spanish. This is inconsistent.
  • For better or worse, the de-facto language of software development is English. Particularly for international collaboration or online open-source development, it is important to use a language that is accessible to more people.

It's a wonderful thing to apply internationalization (i18n) to your strings, but it should be to your strings only, and not the code.

Factor out common code

Consider refactoring your code to:

  • Have only one method that asks for units, called twice (once for source unit and once for destination unit)
  • Make a tuple of coefficient-offset pairs. These represent the linear function from the given unit to Kelvin and back. This will only need two unit conversion formulae, rather than (worst-case) 2^n with the current strategy.

Bug?

Are you sure that this works?

cantidad_temperatura % 9*5 -32

I doubt that modulus is the right thing to do here. You should be using division /.

Example code

Notes:

  • This does a rough i18n, with some strings from Google Translate (so my apologies for the likely poor Spanish).
  • Only English and Spanish are implemented but any other language can be added.
  • This assumes that your operating system is set to the correct locale
  • For these purposes, only the ISO639-1 language without country code is considered
  • Enums are used for stricter type assurance
  • Type hints are used for better static analysis and documentation
  • I have not bothered to add the complexity of input validation, so if input is invalid, there will be an exception thrown
  • Note the use of locale methods rather than direct int and float construction and formatting

strings.py

from locale import getlocale, getdefaultlocale


# For testing only
# from locale import setlocale, LC_ALL
# setlocale(LC_ALL, 'es_ES.UTF8')


def get_lang() -> str:
    lang, _ = getlocale()
    def_lang, _ = getdefaultlocale()
    return (lang or def_lang)[:2]


LANG = get_lang()

if LANG == 'en':
    DIMENSIONS = (
      'Temperature',
      'Length',
      'Mass',
      'Volume',
      'Time',
      'Currency',
    )
    TEMP_UNITS = (
      'Kelvin',
      'Celsius',
      'Fahrenheit',
    )
    ENTER_NUMBER = 'Enter the desired number: '
    CHOOSE_TEMP_SOURCE = 'Choose the source temperature unit to convert: '
    CHOOSE_TEMP_DEST = 'Choose the destination temperature unit to convert: '
    PROVIDE_TEMP = 'Provide the source temperature: '
    RESULT = 'The result of the conversion is:'

elif LANG == 'es':
    DIMENSIONS = (
      'Temperatura',
      'Longitud',
      'Masa',
      'Volumen',
      'Tiempo',
      'Divisa'
    )
    TEMP_UNITS = (
      'Kelvin',
      'Centígrada',
      'Fahrenheit'
    )
    ENTER_NUMBER = 'Entra número deseado: '
    CHOOSE_TEMP_SOURCE = 'Elija la unidad de temperatura fuente para convertir: '
    CHOOSE_TEMP_DEST = 'Elija la unidad de temperatura de destino para convertir: '
    PROVIDE_TEMP = 'Proporcionar la temperatura de la fuente: '
    RESULT = 'El resultado de la conversión es:'

convert.py

from enum import Enum
from locale import format_string, atof, atoi
from typing import TypeVar, Type, Iterable

from strings import *


class Dimension(Enum):
    TEMPERATURE = 1
    LONGITUDE = 2
    MASS = 3
    VOLUME = 4
    TIME = 5
    CURRENCY = 6


class TempUnit(Enum):
    KELVIN = 1
    CELSIUS = 2
    FAHRENHEIT = 3


# To get from this unit to Kelvin:
# kelvin = m * this_unit + b
TEMP_PARAMETERS = {
    # This unit       m  b
    TempUnit.KELVIN: (1, 0),
    TempUnit.CELSIUS: (1, 273.16),
    TempUnit.FAHRENHEIT: (5/9, 273.16 - 5/9*32),
}


InputEnum = TypeVar('InputEnum', bound=Enum)


def enum_from_input(t_enum: Type[InputEnum], labels: Iterable[str]) -> InputEnum:
    print(
        '\n'.join(
            format_string('%d = %s', (enum.value, label))
            for enum, label in zip(t_enum, labels)
        )
    )
    result = t_enum(atoi(input(ENTER_NUMBER)))
    print()
    return result


def main():
    dimension = enum_from_input(Dimension, DIMENSIONS)
    if dimension != Dimension.TEMPERATURE:
        raise NotImplementedError()

    print(CHOOSE_TEMP_SOURCE)
    source = enum_from_input(TempUnit, TEMP_UNITS)
    print(CHOOSE_TEMP_DEST)
    dest = enum_from_input(TempUnit, TEMP_UNITS)

    temp1 = atof(input(PROVIDE_TEMP))

    # Use a simple linear transformation where y = mx + b; first convert to
    # the base unit (Kelvin)
    m, b = TEMP_PARAMETERS[source]
    kelvin = m*temp1 + b

    # Now calculate inverse to the destination unit
    m, b = TEMP_PARAMETERS[dest]
    temp2 = (kelvin - b)/m

    print(format_string('%s %.1f', (RESULT, temp2)))


if __name__ == '__main__':
    main()

Example output

1 = Temperatura
2 = Longitud
3 = Masa
4 = Volumen
5 = Tiempo
6 = Divisa
Entra número deseado: 1

Elija la unidad de temperatura fuente para convertir: 
1 = Kelvin
2 = Centígrada
3 = Fahrenheit
Entra número deseado: 3

Elija la unidad de temperatura de destino para convertir: 
1 = Kelvin
2 = Centígrada
3 = Fahrenheit
Entra número deseado: 2

Proporcionar la temperatura de la fuente: 81
El resultado de la conversión es: 27,2
| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ +1 for localisation. \$\endgroup\$ – Linny Jul 15 at 2:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.