[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

However, the preceding code is not legal Python syntax—the module name in import
statements and dot expressions must be a Python variable, not a string; moreover, in
an import the name is taken literally (not evaluated), and in dot syntax must evaluate
to the object (not its string name). To be generic, addComponents steps through a list of
name strings and relies on import to import and return the module identified by
each string. In fact, the for loop containing these statements works as though all of
these statements were run:


import demoDlg, demoRadio, demoCheck, demoScale
part = demoDlg.Demo(root)
part = demoRadio.Demo(root)
part = demoCheck.Demo(root)
part = demoScale.Demo(root)

But because the script uses a list of name strings, it’s easier to change the set of demos
embedded—simply change the list, not the lines of executable code. Further, such data-
driven code tends to be more compact, less redundant, and easier to debug and main-
tain. Incidentally, modules can also be imported from name strings by dynamically
constructing and running import statements, like this:


for demo in demoModules:
exec('from %s import Demo' % demo) # make and run a from
part = eval('Demo')(root) # fetch known import name by string

The exec statement compiles and runs a Python statement string (here, a from to load
a module’s Demo class); it works here as if the statement string were pasted into the
source code where the exec statement appears. The following achieves the same effect
by running an import statement instead:


for demo in demoModules:
exec('import %s' % demo) # make and run an import
part = eval(demo).Demo(root) # fetch module variable by name too

Because it supports any sort of Python statement, these exec/eval techniques are more
general than the import call, but can also be slower, since they must parse code
strings before running them.† However, that slowness may not matter in a GUI; users
tend to be significantly slower than parsers.


Configuring at construction time


One other alternative worth mentioning: notice how Example 8-32 configures and
repacks each attached demo frame for its role in this GUI:


def addComponents(root):
for demo in demoModules:
module = __import__(demo) # import by name string
part = module.Demo(root) # attach an instance

† As we’ll see later in this book, exec can also be dangerous if it is running code strings fetched from users or
network connections. That’s not an issue for the hardcoded strings used internally in this example.


474 | Chapter 8: A tkinter Tour, Part 1

Free download pdf