Código fuente para pynprcalc.calc.main
"""
Corazón de la caluladora.
La calculadora tiene un *stack* (que es una cola LIFO, lo último que entra es lo
primero que sale). Trabaja con *float*.
Los números se ponen en el *stack*. Los comandos sacan cero o más números del
*stack*, hacen una operación con ellos y ponen el resultado en el *stack*.
Por ejemplo al comienzo el *stack* contiene varios números, los últimos números
están abajo.
::
5
6
2
4
Al usar el comando ``+``, el se toman los últimos dos números del *stack* y se
coloca su suma::
5
6
6
"""
from .. import comandos
[documentos]class Stack:
"""
Implementación de un *stack*.
"""
def __init__(self):
self._lista = []
[documentos] def insertar(self, n):
"""
Insertar un número en el stack.
Args:
n (float): Número a insertar.
"""
self._lista.append(n)
[documentos] def pop(self):
"""
Sacar un número del *stack*.
Elimina el número del *stack*.
Returns:
float: Número obtenido desde el *stack*.
"""
return self._lista.pop()
[documentos] def lista(self):
"""
Devuelve una lista que representa al *stack*.
Para por ejemplo mostrar el *stack* en pantalla y acceder a los
elementos sin usar ``pop()``.
"""
return self._lista
[documentos]class Calc:
"""
Calculadora en sí.
Tiene un *stack* y permite correr comandos sobre ese *stack*.
"""
def __init__(self):
self._stack = Stack()
[documentos] def insertar(self, n):
"""
Insertar un número en el *stack* de la calculadora.
Args:
n (float): Número a insertar.
"""
self._stack.insertar(n)
[documentos] def ejecutar(self, comando):
"""
Ejecutar un comando en la calculadora.
Si el comando es un número, lo agrega al *stack*.
Args:
comando (Union[str, float]): Comando a ejecutar.
Raises:
ValueError cuando el comando no existe.
"""
try: # en el caso que sea un numero
self._stack.insertar(float(comando))
except ValueError: # en el caso que no sea un numero
try:
funcion, cant_args = comandos.obtener_funcion(comando)
except ValueError: # en el caso que el comando no exista
raise ValueError('el comando "{}" no existe'.format(comando))
# sacar la cantidad correcta de numeros desde el *stack*
args = []
for i in range(cant_args):
args.append(self._stack.pop())
# usar esos argumentos para llamar la función y guardar el resultado
# en el stack
# si devuelve una lista es porque hay varios elementos a guardar
resultado = funcion(*args)
if resultado is None:
return
if type(resultado) is list:
for n in resultado:
self._stack.insertar(n)
else:
self._stack.insertar(resultado)
[documentos] def lista(self):
"""
Devuelve una lista que representa al *stack*.
Para por ejemplo mostrar el *stack* en pantalla y acceder a los
elementos sin usar ``pop()``.
"""
return self._stack.lista()