eval
Parses, evaluates, and returns the result of a Python expression represented as a
string.
exec
Runs an arbitrary Python statement represented as a string, and has no return value.
Both accept optional dictionaries to be used as global and local namespaces for assign-
ing and evaluating names used in the code strings. In the calculator, self.names be-
comes a symbol table for running calculator expressions. A related Python function,
compile, can be used to precompile code strings to code objects before passing them to
eval and exec (use it if you need to run the same string many times).
By default, a code string’s namespace defaults to the caller’s namespaces. If we didn’t
pass in dictionaries here, the strings would run in the eval method’s namespace. Since
the method’s local namespace goes away after the method call returns, there would be
no way to retain names assigned in the string. Notice the use of nested exception han-
dlers in the class’s eval method:
- It first assumes the string is an expression and tries the built-in eval function.
- If that fails because of a syntax error, it tries evaluating the string as a statement
using exec. - Finally, if both attempts fail, it reports an error in the string (a syntax error, unde-
fined name, and so on).
Statements and invalid expressions might be parsed twice, but the overhead doesn’t
matter here, and you can’t tell whether a string is an expression or a statement without
parsing it manually. Note that the “eval” button evaluates expressions, but = sets Python
variables by running an assignment statement. Variable names are combinations of the
letter keys “abcd” (or any name typed directly). They are assigned and evaluated in a
dictionary used to represent the calculator’s namespace and retained for the session.
Extending and attaching
Clients that reuse this calculator are as simple as the calculator itself. Like most class-
based tkinter GUIs, this one can be extended in subclasses—Example 19-18 customizes
the simple calculator’s constructor to add extra widgets.
Example 19-18. PP4E\Lang\Calculator\calc0ext.py
from tkinter import *
from calc0 import CalcGui
class Inner(CalcGui): # extend GUI
def init(self):
CalcGui.init(self)
Label(self, text='Calc Subclass').pack() # add after
Button(self, text='Quit', command=self.quit).pack() # top implied
PyCalc: A Calculator Program/Object | 1461