Quiz Flashcards

(185 cards)

1
Q

How can you determine how large a tuple is? Why is this tool located where it is?

A

The built-in len function returns the length (number of contained items) for any container object in Python, including tuples. It is a built-in function instead of a type method because it applies to many different types of objects. In general, built- in functions and expressions may span many object types; methods are specific to a single object type, though some may be available on more than one type (index, for example, works on lists and tuples).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Writeanexpressionthatchangesthefirstiteminatuple.(4, 5, 6)shouldbecome (1, 5, 6) in the process.

A

Because they are immutable, you canÕt really change tuples in place, but you can generate a new tuple with the desired value. Given T = (4, 5, 6), you can change the first item by making a new tuple from its parts by slicing and concatenating: T = (1,) + T[1:].(Recallthatsingle-itemtuplesrequireatrailingcomma.)Youcould also convert the tuple to a list, change it in place, and convert it back to a tuple, but this is more expensive and is rarely required in practiceÑsimply use a list if you know that the object will require in-place changes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is the default for the processing mode argument in a file open call?

A

The default for the processing mode argument in a file open call is ‘r’, for reading text input. For input text files, simply pass in the external fileÕs name.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What module might you use to store Python objects in a file without converting them to strings yourself?

A

The pickle module can be used to store Python objects in a file without explicitly converting them to strings. The struct module is related, but it assumes the data is to be in packed binary format in the file; json similarly converts a limited set of Python objects to and from strings per the JSON format.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How might you go about copying all parts of a nested structure at once?

A

Import the copy module, and call copy.deepcopy(X) if you need to copy all parts of a nested structure X. This is also rarely seen in practice; references are usually the desired behavior, and shallow copies (e.g., aList[:], aDict.copy(), set(aSet)) usually suffice for most copies.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

When does Python consider an object true?

A

An object is considered true if it is either a nonzero number or a nonempty collec- tion object. The built-in words True and False are essentially predefined to have the same meanings as integer 1 and 0, respectively.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is your quest?

A

Acceptable answers include ÒTo learn Python,Ó ÒTo move on to the next part of the book,Ó or ÒTo seek the Holy Grail.Ó

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What conclusions can you draw from this chapter about the relative speed of Python iteration tools?

A

In general, list comprehensions are usually the quickest of the bunch; map beats list comprehensions in Python only when all tools must call functions; for loops tend to be slower than comprehensions; and generator functions and expressions are slower than comprehensions by a constant factor. Under PyPy, some of these find- ings differ; map often turns in a different relative performance, for example, and list comprehensions seem always quickest, perhaps due to function-level optimiza- tions. At least thatÕs the case today on the Python versions tested, on the test machine used, and for the type of code timedÑthese results may vary if any of these three variables differ. Use the homegrown timer or standard library timeit to test your use cases for more relevant results. Also keep in mind that iteration is just one component of a programÕs time: more code gives a more complete picture.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What conclusions can you draw from this chapter about the relative speed of the Pythons timed?

A

In general, PyPy 1.9 (implementing Python 2.7) is typically faster than CPython 2.7, and CPython 2.7 is often faster than CPython 3.3. In most cases timed, PyPy is some 10X faster than CPython, and CPython 2.7 is often a small constant faster than CPython 3.3. In cases that use integer math, CPython 2.7 can be 10X faster than CPython 3.3, and PyPy can be 100X faster than 3.3. In other cases (e.g., string operations and file iterators), PyPy can be slower than CPython by 10X, though timeit and memory management differences may influence some results. The pystone benchmark confirms these relative rankings, though the sizes of the dif- ferences it reports differ due to the code timed. At least thatÕs the case today on the Python versions tested, on the test machine used, and for the type of code timedÑthese results may vary if any of these three variables differ. Use the homegrown timer or standard library timeit to test your use cases for more relevant results. This is especially true when timing Python implementations, which may be arbitrarily optimized in each new release.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is the point of coding functions?

A

Functions are the most basic way of avoiding code redundancy in PythonÑfactor- ing code into functions means that we have only one copy of an operationÕs code to update in the future. Functions are also the basic unit of code reuse in Python Ñwrapping code in functions makes it a reusable tool, callable in a variety of pro- grams. Finally, functions allow us to divide a complex system into manageable parts, each of which may be developed individually.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

At what time does Python create a function?

A

A function is created when Python reaches and runs the def statement; this state- ment creates a function object and assigns it the functionÕs name. This normally happens when the enclosing module file is imported by another module (recall that imports run the code in a file from top to bottom, including any defs), but it can also occur when a def is typed interactively or nested in other statements, such as ifs.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What does a function return if it has no return statement in it?

A

A function returns the None object by default if the control flow falls off the end of the function body without running into a return statement. Such functions are usually called with expression statements, as assigning their None results to vari- ables is generally pointless. A return statement with no expression in it also returns None.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

When does the code nested inside the function definition statement run?

A

The function body (the code nested inside the function definition statement) is run when the function is later called with a call expression. The body runs anew each time the function is called.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

WhatÕs wrong with checking the types of objects passed into a function?

A

Checking the types of objects passed into a function effectively breaks the func- tionÕs flexibility, constraining the function to work on specific types only. Without such checks, the function would likely be able to process an entire range of object typesÑany objects that support the interface expected by the function will work. (The term interface means the set of methods and expression operators the func- tionÕs code runs.)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What is a metaclass?

A

A metaclass is a class used to create a class. Normal new-style classes are instances of the type class by default. Metaclasses are usually subclasses of the type class, which redefines class creation protocol methods in order to customize the class creation call issued at the end of a class statement; they typically redefine the methods __new__ and __init__ to tap into the class creation protocol. Metaclasses can also be coded other waysÑas simple functions, for exampleÑbut they are always responsible for making and returning an object for the new class. Meta- classes may have methods and data to provide behavior for their classes tooÑand constitute a secondary pathway for inheritance searchÑbut their attributes are accessible only to their class instances, not to their instanceÕs instances.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How do you declare the metaclass of a class?

A

In Python 3.X, use a keyword argument in the class header line: class C(meta class=M). In Python 2.X, use a class attribute instead: __metaclass__ = M. In 3.X, the class header line can also name normal superclasses before the metaclass key- word argument; in 2.X you generally should derive from object too, though this is sometimes optional.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

How do class decorators overlap with metaclasses for managing classes?

A

Because both are automatically triggered at the end of a class statement, class decorators and metaclasses can both be used to manage classes. Decorators rebind a class name to a callableÕs result and metaclasses route class creation through a callable, but both hooks can be used for similar purposes. To manage classes, decorators simply augment and return the original class objects. Metaclasses aug- ment a class after they create it. Decorators may have a slight disadvantage in this role if a new class must be defined, because the original class has already been created.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

How do class decorators overlap with metaclasses for managing instances?

A

Because both are automatically triggered at the end of a class statement, we can use both class decorators and metaclasses to manage class instances, by inserting a wrapper (proxy) object to catch instance creation calls. Decorators may rebind the class name to a callable run on instance creation that retains the original class object. Metaclasses can do the same, but may have a slight disadvantage in this role, because they must also create the class object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Would you rather count decorators or metaclasses amongst your weaponry? (And please phrase your answer in terms of a popular Monty Python skit.)

A

Our chief weapon is decorators…decorators and metaclasses…metaclasses and decorators… Our two weapons are metaclasses and decorators…and ruthless effi- ciency… Our three weapons are metaclasses, decorators, and ruthless effi- ciency…and an almost fanatical devotion to Python… Our four…no… Amongst our weapons… Amongst our weaponry…are such elements as metaclasses, decora- tors… IÕll come in again…

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

What is multiple inheritance?

A

Multiple inheritance occurs when a class inherits from more than one superclass; itÕs useful for mixing together multiple packages of class-based code. The left-to- right order in class statement headers determines the general order of attribute searches.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

What is delegation?

A

Delegationinvolveswrappinganobjectinaproxyclass,whichaddsextrabehavior and passes other operations to the wrapped object. The proxy retains the interface of the wrapped object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

What is composition?

A

Composition is a technique whereby a controller class embeds and directs a num- ber of objects, and provides an interface all its own; itÕs a way to build up larger structures with classes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

What are bound methods?

A

Bound methods combine an instance and a method function; you can call them without passing in an instance object explicitly because the original instance is still available.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

What are pseudoprivate attributes used for?

A

Pseudoprivate attributes (whose names begin but do not end with two leading underscores: __X) are used to localize names to the enclosing class. This includes both class attributes like methods defined inside the class, and self instance at- tributes assigned inside the classÕs methods. Such names are expanded to include the class name, which makes them generally unique.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
How might you code a multiway branch in Python?
An if statement with multiple elif clauses is often the most straightforward way to code a multiway branch, though not necessarily the most concise or flexible. Dictionary indexing can often achieve the same result, especially if the dictionary contains callable functions coded with def statements or lambda expressions.
26
How can you code an if/else statement as an expression in Python?
In Python 2.5 and later, the expression form Y if X else Z returns Y if X is true, or Z otherwise; itÕs the same as a four-line if statement. The and/or combination (((X and Y) or Z))canworkthesameway,butitÕsmoreobscureandrequiresthat the Y part be true.
27
How can you make a single statement span many lines?
Wrap up the statement in an open syntactic pair ((), [], or {}), and it can span as many lines as you like; the statement ends when Python sees the closing (right) half of the pair, and lines 2 and beyond of the statement can begin at any indentation level. Backslash continuations work too, but are broadly discouraged in the Python world.
28
What do the words True and False mean?
True and False are just custom versions of the integers 1 and 0, respectively: they always stand for Boolean true and false values in Python. TheyÕre available for use in truth tests and variable initialization, and are printed for expression results at the interactive prompt. In all these roles, they serve as a more mnemonic and hence readable alternative to 1 and 0.
29
How can you start an interactive interpreter session?
YoucanstartaninteractivesessiononWindows7andearlierbyclickingyourStart button, picking the All Programs option, clicking the Python entry, and selecting the ÒPython (command line)Ó menu option. You can also achieve the same effect on Windows and other platforms by typing python as a system command line in your systemÕs console window (a Command Prompt window on Windows). An- other alternative is to launch IDLE, as its main Python shell window is an interactive session. Depending on your platform and Python, if you have not set your systemÕs PATH variable to find Python, you may need to cd to where Python is installed, or type its full directory path instead of just python (e.g., C:\Python33\python on Win- dows, unless youÕre using the 3.3 launcher).
30
Where do you type a system command line to launch a script file?
You type system command lines in whatever your platform provides as a system console: a Command Prompt window on Windows; an xterm or terminal window on Unix, Linux, and Mac OS X; and so on. You type this at the systemÕs prompt, not at the Python interactive interpreterÕs Ò\>\>\>Ó promptÑbe careful not to con- fuse these prompts.
31
Name four or more ways to run the code saved in a script file.
Code in a script (really, module) file can be run with system command lines, file icon clicks, imports and reloads, the exec built-in function, and IDE GUI selections such as IDLEÕs Run\_Run Module menu option. On Unix, they can also be run as executables with the #! trick, and some platforms support more specialized launch- ing techniques (e.g., drag and drop). In addition, some text editors have unique ways to run Python code, some Python programs are provided as standalone Òfro- zen binaryÓ executables, and some systems use Python code in embedded mode, where it is run automatically by an enclosing program written in a language like C, C++, or Java. The latter technique is usually done to provide a user customi- zation layer.
32
Name two pitfalls related to clicking file icons on Windows.
Scripts that print and then exit cause the output file to disappear immediately, before you can view the output (which is why the input trick comes in handy); error messages generated by your script also appear in an output window that closes before you can examine its contents (which is one reason that system com- mand lines and IDEs such as IDLE are better for most development).
33
Why might you need to reload a module?
Python imports (loads) a module only once per process, by default, so if youÕve changed its source code and want to run the new version without stopping and restarting Python, youÕll have to reload it. You must import a module at least once before you can reload it. Running files of code from a system shell command line, via an icon click, or via an IDE such as IDLE generally makes this a nonissue, as those launch schemes usually run the current version of the source code file each time.
34
How do you run a script from within IDLE?
Within the text edit window of the file you wish to run, select the windowÕs Run\_Run Module menu option. This runs the windowÕs source code as a top-level script file and displays its output back in the interactive Python shell window.
35
Name two pitfalls related to using IDLE.
IDLE can still be hung by some types of programsÑespecially GUI programs that perform multithreading (an advanced technique beyond this bookÕs scope). Also, IDLE has some usability features that can burn you once you leave the IDLE GUI: a scriptÕs variables are automatically imported to the interactive scope in IDLE and working directories are changed when you run a file, for instance, but Python itself does not take such steps in general.
36
What is a namespace, and how does it relate to module files?
A namespace is just a package of variables (i.e., names). It takes the form of an object with attributes in Python. Each module file is automatically a namespaceÑ that is, a package of variables reflecting the assignments made at the top level of the file. Namespaces help avoid name collisions in Python programs: because each module file is a self-contained namespace, files must explicitly import other files in order to use their names.
37
Name three things that exception processing is good for.
Exception processing is useful for error handling, termination actions, and event notification. It can also simplify the handling of special cases and can be used to implement alternative control flows as a sort of structured Ògo toÓ operation. In general, exception processing also cuts down on the amount of error-checking code your program may requireÑbecause all errors filter up to handlers, you may not need to test the outcome of every operation.
38
What happens to an exception if you donÕt do anything special to handle it?
Any uncaught exception eventually filters up to the default exception handler Python provides at the top of your program. This handler prints the familiar error message and shuts down your program.
39
How can your script recover from an exception?
If you donÕt want the default message and shutdown, you can code try/except statements to catch and recover from exceptions that are raised within its nested code block. Once an exception is caught, the exception is terminated and your program continues after the try.
40
Name two ways to trigger exceptions in your script.
The raise and assert statements can be used to trigger an exception, exactly as if it had been raised by Python itself. In principle, you can also raise an exception by making a programming mistake, but thatÕs not usually an explicit goal!
41
Name two ways to specify actions to be run at termination time, whether an ex- ception occurs or not.
The try/finally statement can be used to ensure actions are run after a block of code exits, regardless of whether the block raises an exception or not. The with/ as statement can also be used to ensure termination actions are run, but only when processing object types that support it.
42
How does a module source code file become a module object?
A moduleÕs source code file automatically becomes a module object when that module is imported. Technically, the moduleÕs source code is run during the import, one statement at a time, and all the names assigned in the process become attributes of the module object.
43
Why might you have to set your PYTHONPATH environment variable?
You only need to set PYTHONPATH to import from directories other than the one in which you are working (i.e., the current directory when working interactively, or the directory containing your top-level file). In practice, this will be a common case for nontrivial programs.
44
Name the five major components of the module import search path.
The five major components of the module import search path are the top-level scriptÕs home directory (the directory containing it), all directories listed in the PYTHONPATH environment variable, the standard library directories, all directories listed in .pth path files located in standard places, and the site-packages root di- rectory for third-party extension installs. Of these, programmers can customize PYTHONPATH and .pth files.
45
Name four file types that Python might load in response to an import operation.
Python might load a source code (.py) file, a byte code (.pyc or .pyo) file, a C ex- tension module (e.g., a .so file on Linux or a .dll or .pyd file on Windows), or a directory of the same name for package imports. Imports may also load more exotic things such as ZIP file components, Java classes under the Jython version of Python, .NET components under IronPython, and statically linked C extensions that have no files present at all. In fact, with import hooks, imports can load arbi- trary items.
46
What is a namespace, and what does a moduleÕs namespace contain?
A namespace is a self-contained package of variables, which are known as the attributes of the namespace object. A moduleÕs namespace contains all the names assigned by code at the top level of the module file (i.e., not nested in def or class statements). Technically, a moduleÕs global scope morphs into the module objectÕs attributes namespace. A moduleÕs namespace may also be altered by as- signments from other files that import it, though this is generally frowned upon (see Chapter 17 for more on the downsides of cross-file changes).
47
What is the difference between enclosing a list comprehension in square brackets and parentheses?
List comprehensions in square brackets produce the result list all at once in memory. When they are enclosed in parentheses instead, they are actually generator expressionsÑthey have a similar meaning but do not produce the result list all at once. Instead, generator expressions return a generator object, which yields one item in the result at a time when used in an iteration context.
48
How are generators and iterators related?
Generators are iterable objects that support the iteration protocol automaticallyÑ they have an iterator with a \_\_next\_\_ method (next in 2.X) that repeatedly advances to the next item in a series of results and raises an exception at the end of the series. In Python, we can code generator functions with def and yield, generator expres- sions with parenthesized comprehensions, and generator objects with classes that define a special method named \_\_iter\_\_ (discussed later in the book).
49
How can you tell if a function is a generator function?
A generator function has a yield statement somewhere in its code. Generator functions are otherwise identical to normal functions syntactically, but they are compiled specially by Python so as to return an iterable generator object when called. That object retains state and code location between values.
50
What does a yield statement do?
When present, this statement makes Python compile the function specially as a generator; when called, the function returns a generator object that supports the iteration protocol. When the yield statement is run, it sends a result back to the caller and suspends the functionÕs state; the function can then be resumed after the last yield statement, in response to a next built-in or \_\_next\_\_ method call issued by the caller. In more advanced roles, the generator send method similarly resumes the generator, but can also pass a value that shows up as the yield expressionÕs value. Generator functions may also have a return statement, which terminates the generator.
51
How are map calls and list comprehensions related? Compare and contrast the two.
The map call is similar to a list comprehensionÑboth produce a series of values, by collecting the results of applying an operation to each item in a sequence or other iterable, one item at a time. The primary difference is that map applies a function call to each item, and list comprehensions apply arbitrary expressions. Because of this, list comprehensions are more general; they can apply a function call expres- sion like map, but map requires a function to apply other kinds of expressions. List comprehensions also support extended syntax such as nested for loops and if clauses that subsume the filter built-in. In Python 3.X, map also differs in that it produces a generator of values; the list comprehension materializes the result list in memory all at once. In 2.X, both tools create result lists.
52
(This question is a repeat from the first quiz in Chapter 1Ñsee, I told you it would be easy! :-) Why does ÒspamÓ show up in so many Python examples in books and on the Web?
Because Python is named after the British comedy group Monty Python (based on surveys IÕve conducted in classes, this is a much-too-well-kept secret in the Python world!). The spam reference comes from a Monty Python skit, set in a cafeteria whose menu items all seem to come with Spam. A couple trying to order food there keeps getting drowned out by a chorus of Vikings singing a song about Spam. No, really. And if I could insert an audio clip of that song here, I would...
53
How are for loops and iterable objects related?
The for loop uses the iteration protocol to step through items in the iterable object across which it is iterating. It first fetches an iterator from the iterable by passing the object to iter, and then calls this iterator objectÕs \_\_next\_\_ method in 3.X on each iteration and catches the StopIteration exception to determine when to stop looping. The method is named next in 2.X, and is run by the next built-in function in both 3.x and 2.X. Any object that supports this model works in a for loop and in all other iteration contexts. For some objects that are their own iterator, the initial iter call is extraneous but harmless.
54
How are for loops and list comprehensions related?
Both are iteration tools and contexts. List comprehensions are a concise and often efficient way to perform a common for loop task: collecting the results of applying an expression to all items in an iterable object. ItÕs always possible to translate a list comprehension to a for loop, and part of the list comprehension expression looks like the header of a for loop syntactically.
55
Name four iteration contexts in the Python language.
Iteration contexts in Python include the for loop; list comprehensions; the map built-in function; the in membership test expression; and the built-in functions sorted, sum, any, and all. This category also includes the list and tuple built-ins, string join methods, and sequence assignments, all of which use the iteration pro- tocol (see answer #1) to step across iterable objects one item at a time.
56
What is the best way to read line by line from a text file today?
The best way to read lines from a text file today is to not read it explicitly at all: instead, open the file within an iteration context tool such as a for loop or list comprehension, and let the iteration tool automatically scan one line at a time by running the fileÕs next handler method on each iteration. This approach is generally best in terms of coding simplicity, memory space, and possibly execution speed requirements.
57
What sort of weapons would you expect to see employed by the Spanish Inquisi- tion?
IÕll accept any of the following as correct answers: fear, intimidation, nice red uni- forms, a comfy chair, and soft pillows.
58
How do \_\_getattr\_\_ and \_\_getattribute\_\_ differ?
The \_\_getattr\_\_ method is run for fetches of undefined attributes only (i.e., those not present on an instance and not inherited from any of its classes). By contrast, the \_\_getattribute\_\_ method is called for every attribute fetch, whether the at- tribute is defined or not. Because of this, code inside a \_\_getattr\_\_ can freely fetch other attributes if they are defined, whereas \_\_getattribute\_\_ must use special code for all such attribute fetches to avoid looping or extra calls (it must route fetches to a superclass to skip itself).
59
How do properties and descriptors differ?
Propertiesserveaspecificrole,whiledescriptorsaremoregeneral.Propertiesdefine get, set, and delete functions for a specific attribute; descriptors provide a class with methods for these actions, too, but they provide extra flexibility to support more arbitrary actions. In fact, properties are really a simple way to create a specific kind of descriptorÑone that runs functions on attribute accesses. Coding differs too: a property is created with a built-in function, and a descriptor is coded with a class; thus, descriptors can leverage all the usual OOP features of classes, such as inheritance. Moreover, in addition to the instanceÕs state information, descrip- tors have local state of their own, so they can sometimes avoid name collisions in the instance.
60
How are properties and decorators related?
Properties can be coded with decorator syntax. Because the property built-in ac- cepts a single function argument, it can be used directly as a function decorator to define a fetch access property. Due to the name rebinding behavior of decorators, the name of the decorated function is assigned to a property whose get accessor is set to the original function decorated (name = property(name)). Property setter and deleter attributes allow us to further add set and delete accessors with deco- ration syntaxÑthey set the accessor to the decorated function and return the aug- mented property.
61
What are the main functional differences between \_\_getattr\_\_ and \_\_getattri bute\_\_ and properties and descriptors?
The\_\_getattr\_\_and\_\_getattribute\_\_methodsaremoregeneric:theycanbeused to catch arbitrarily many attributes. In contrast, each property or descriptor pro- vides access interception for only one specific attributeÑwe canÕt catch every at- tribute fetch with a single property or descriptor. On the other hand, properties and descriptors handle both attribute fetch and assignment by design: \_\_get attr\_\_ and \_\_getattribute\_\_ handle fetches only; to intercept assignments as well, \_\_setattr\_\_ must also be coded. The implementation is also different: \_\_get attr\_\_ and \_\_getattribute\_\_ are operator overloading methods, whereas proper- ties and descriptors are objects manually assigned to class attributes. Unlike the others, properties and descriptors can also sometimes avoid extra calls on assign- ment to unmanaged names, and show up in dir results automatically, but are also narrower in scopeÑthey canÕt address generic dispatch goals. In Python evolution, new features tend to offer alternatives, but do not fully subsume what came before.
62
IsnÕt all this feature comparison just a kind of argument?
No it isnÕt. To quote from Python namesake Monty PythonÕs Flying Circus: An argument is a connected series of statements intended to establish a proposition. No it isn't. Yes it is! It's not just contradiction. Look, if I argue with you, I must take up a contrary position. Yes, but that's not just saying "No it isn't." Yes it is! No it isn't! Yes it is! No it isn't. Argument is an intellectual process. Contradiction is just the automatic gainsaying of any statement the other person makes. (short pause) No it isn't. It is. Not at all. Now look...
63
What are the main functional differences between a while and a for?
The while loop is a general looping statement, but the for is designed to iterate across items in a sequence or other iterable. Although the while can imitate the for with counter loops, it takes more code and might run slower.
64
WhatÕs the difference between break and continue?
The break statement exits a loop immediately (you wind up below the entire while or for loop statement), and continue jumps back to the top of the loop (you wind up positioned just before the test in while or the next item fetch in for).
65
When is a loopÕs else clause executed?
The else clause in a while or for loop will be run once as the loop is exiting, if the loop exits normally (without running into a break statement). A break exits the loop immediately, skipping the else part on the way out (if there is one).
66
How can you code a counter-based loop in Python?
Counter loops can be coded with a while statement that keeps track of the index manually, or with a for loop that uses the range built-in function to generate suc- cessive integer offsets. Neither is the preferred way to work in Python, if you need to simply step across all the items in a sequence. Instead, use a simple for loop instead, without range or counters, whenever possible; it will be easier to code and usually quicker to run.
67
What can a range be used for in a for loop?
The range built-in can be used in a for to implement a fixed number of repetitions, to scan by offsets instead of items at offsets, to skip successive items as you go, and to change a list while stepping across it. None of these roles requires range, and most have alternativesÑscanning actual items, three-limit slices, and list compre- hensions are often better solutions today (despite the natural inclinations of exÐC programmers to want to count things!).
68
Name two ways to build a list containing five integer zeros.
A literal expression like [0, 0, 0, 0, 0] and a repetition expression like [0] \* 5 will each create a list of five zeros. In practice, you might also build one up with a loop that starts with an empty list and appends 0 to it in each iteration, with L.append(0). A list comprehension ([0 for i in range(5)]) could work here, too, but this is more work than you need to do for this answer.
69
Name two ways to build a dictionary with two keys, 'a' and 'b', each having an associated value of 0.
A literal expression such as {'a': 0, 'b': 0} or a series of assignments like D = {}, D['a'] = 0, and D['b'] = 0 would create the desired dictionary. You can also use the newer and simpler-to-code dict(a=0, b=0) keyword form, or the more flexibledict([('a', 0), ('b', 0)])key/valuesequencesform.Or,becauseallthe values are the same, you can use the special form dict.fromkeys('ab', 0). In 3.X and2.7,youcanalsouseadictionarycomprehension:{k:0 for k in 'ab'},though again, this may be overkill here.
70
Name four operations that change a list object in place.
The append and extend methods grow a list in place, the sort and reverse methods order and reverse lists, the insert method inserts an item at an offset, the remove and pop methods delete from a list by value and by position, the del statement deletes an item or slice, and index and slice assignment statements replace an item or entire section. Pick any four of these for the quiz.
71
Name four operations that change a dictionary object in place.
Dictionaries are primarily changed by assignment to a new or existing key, which creates or changes the keyÕs entry in the table. Also, the del statement deletes a keyÕs entry, the dictionary update method merges one dictionary into another in place, and D.pop(key) removes a key and returns the value it had. Dictionaries also have other, more exotic in-place change methods not presented in this chapter, such as setdefault; see reference sources for more details.
72
Why might you use a dictionary instead of a list?
Dictionariesaregenerallybetterwhenthedataislabeled(arecordwithfieldnames, for example); lists are best suited to collections of unlabeled items (such as all the files in a directory). Dictionary lookup is also usually quicker than searching a list, though this might vary per program.
73
What is an abstract superclass?
An abstract superclass is a class that calls a method, but does not inherit or define itÑit expects the method to be filled in by a subclass. This is often used as a way to generalize classes when behavior cannot be predicted until a more specific sub- class is coded. OOP frameworks also use this as a way to dispatch to client-defined, customizable operations.
74
What happens when a simple assignment statement appears at the top level of a class statement?
When a simple assignment statement (X = Y) appears at the top level of a class statement, it attaches a data attribute to the class (Class.X). Like all class attributes, this will be shared by all instances; data attributes are not callable method func- tions, though.
75
Why might a class need to manually call the \_\_init\_\_ method in a superclass?
A class must manually call the \_\_init\_\_ method in a superclass if it defines an \_\_init\_\_ constructor of its own and still wants the superclassÕs construction code to run. Python itself automatically runs just one constructorÑthe lowest one in the tree. Superclass constructors are usually called through the class name, passing in the self instance manually: Superclass.\_\_init\_\_(self, ...).
76
How can you augment, instead of completely replacing, an inherited method?
To augment instead of completely replacing an inherited method, redefine it in a subclass, but call back to the superclassÕs version of the method manually from the new version of the method in the subclass. That is, pass the self instance to the superclassÕs version of the method manually: Superclass.method(self, ...).
77
How does a classÕs local scope differ from that of a function?
A class is a local scope and has access to enclosing local scopes, but it does not serve as an enclosing local scope to further nested code. Like modules, the class local scope morphs into an attribute namespace after the class statement is run.
78
What...was the capital of Assyria?
Ashur (or Qalat Sherqat), Calah (or Nimrud), the short-lived Dur Sharrukin (or Khorsabad), and finally Nineveh.
79
What are the names and roles of string object types in Python 3.X?
Python 3.X has three string types: str (for Unicode text, including ASCII), bytes (for binary data with absolute byte values), and bytearray (a mutable flavor of bytes). The str type usually represents content stored on a text file, and the other two types generally represent content stored on binary files.
80
What are the names and roles of string object types in Python 2.X?
Python 2.X has two main string types: str (for 8-bit text and binary data) and unicode (for possibly wider character Unicode text). The str type is used for both text and binary file content; unicode is used for text file content that is generally more complex than 8-bit characters. Python 2.6 (but not earlier) also has 3.XÕs bytearray type, but itÕs mostly a back-port and doesnÕt exhibit the sharp text/binary distinction that it does in 3.X.
81
What is the mapping between 2.X and 3.X string types?
The mapping from 2.X to 3.X string types is not direct, because 2.XÕs str equates to both str and bytes in 3.X, and 3.XÕs str equates to both str and unicode in 2.X. The mutability of bytearray in 3.X is also unique. In general, though: Unicode text is handled by 3.X str and 2.X unicode, byte-based data is handled by 3.X bytes and 2.X str, and 3.X bytes and 2.X str can both handle some simpler types of text.
82
How do Python 3.XÕs string types differ in terms of operations?
Python 3.XÕs string types share almost all the same operations: method calls, se- quence operations, and even larger tools like pattern matching work the same way. On the other hand, only str supports string formatting operations, and bytear ray has an additional set of operations that perform in-place changes. The str and bytes types also have methods for encoding and decoding text, respectively.
83
How can you code non-ASCII Unicode characters in a string in 3.X?
Non-ASCII Unicode characters can be coded in a string with both hex (\xNN) and Unicode (\uNNNN, \UNNNNNNNN) escapes. On some machines, some non-ASCII char- actersÑcertain Latin-1 characters, for exampleÑcan also be typed or pasted di- rectly into code, and are interpreted per the UTF-8 default or a source code en- coding directive comment.
84
What are the main differences between text- and binary-mode files in Python 3.X?
In 3.X, text-mode files assume their file content is Unicode text (even if itÕs all ASCII) and automatically decode when reading and encode when writing. With binary-mode files, bytes are transferred to and from the file unchanged. The con- tents of text-mode files are usually represented as str objects in your script, and the contents of binary files are represented as bytes (or bytearray) objects. Text- mode files also handle the BOM for certain encoding types and automatically translate end-of-line sequences to and from the single \n character on input and output unless this is explicitly disabled; binary-mode files do not perform either of these steps. Python 2.X uses codecs.open for Unicode files, which encodes and decodes similarly; 2.XÕs open only translates line ends in text mode.
85
How would you read a Unicode text file that contains text in a different encoding than the default for your platform?
To read files encoded in a different encoding than the default for your platform, simply pass the name of the fileÕs encoding to the open built-in in 3.X (codecs.open() in 2.X); data will be decoded per the specified encoding when it is read from the file. You can also read in binary mode and manually decode the bytes to a string by giving an encoding name, but this involves extra work and is some- what error-prone for multibyte characters (you may accidentally read a partial character sequence).
86
How can you create a Unicode text file in a specific encoding format?
To create a Unicode text file in a specific encoding format, pass the desired en- coding name to open in 3.X (codecs.open() in 2.X); strings will be encoded per the desired encoding when they are written to the file. You can also manually encode a string to bytes and write it in binary mode, but this is usually extra work.
87
Why is ASCII text considered to be a kind of Unicode text?
ASCII text is considered to be a kind of Unicode text, because its 7-bit range of values is a subset of most Unicode encodings. For example, valid ASCII text is also valid Latin-1 text (Latin-1 simply assigns the remaining possible values in an 8-bit byte to additional characters) and valid UTF-8 text (UTF-8 defines a variable-byte scheme for representing more characters, but ASCII characters are still represented with the same codes, in a single byte). This makes Unicode backward-compatible with the mass of ASCII text data in the world (though it also may have limited its optionsÑself-identifying text, for instance, may have been difficult (though BOMs serve much the same role).
88
How large an impact does Python 3.XÕs string types change have on your code?
The impact of Python 3.XÕs string types change depends upon the types of strings you use. For scripts that use simple ASCII text on platforms with ASCII-compatible default encodings, the impact is probably minor: the str string type works the same in 2.X and 3.X in this case. Moreover, although string-related tools in the standard library such as re, struct, pickle, and xml may technically use different types in 3.X than in 2.X, the changes are largely irrelevant to most programs because 3.XÕs str and bytes and 2.XÕs str support almost identical interfaces. If you process Unicode data, the toolset you need has simply moved from 2.XÕs unicode and codecs.open() to 3.XÕs str and open. If you deal with binary data files, youÕll need to deal with content as bytes objects; since they have a similar interface to 2.X strings, though, the impact should again be minimal. That said, the update of the book Programming Python for 3.X ran across numerous cases where UnicodeÕs mandatory status in 3.X implied changes in standard library APIsÑfrom network- ing and GUIs, to databases and email. In general, Unicode will probably impact most 3.X users eventually.
89
What two operator overloading methods can you use to support iteration in your classes?
Classes can support iteration by defining (or inheriting) \_\_getitem\_\_ or \_\_iter\_\_. In all iteration contexts, Python tries to use \_\_iter\_\_ first, which returns an object that supports the iteration protocol with a \_\_next\_\_ method: if no \_\_iter\_\_ is found by inheritance search, Python falls back on the \_\_getitem\_\_ indexing method, which is called repeatedly, with successively higher indexes. If used, the yield statement can create the \_\_next\_\_ method automatically.
90
What two operator overloading methods handle printing, and in what contexts?
The \_\_str\_\_ and \_\_repr\_\_ methods implement object print displays. The former is called by the print and str built-in functions; the latter is called by print and str if there is no \_\_str\_\_, and always by the repr built-in, interactive echoes, and nested appearances. That is, \_\_repr\_\_ is used everywhere, except by print and str when a \_\_str\_\_ is defined. A \_\_str\_\_ is usually used for user-friendly displays; \_\_repr\_\_ gives extra details or the objectÕs as-code form.
91
How can you intercept slice operations in a class?
Slicingiscaughtbythe\_\_getitem\_\_indexingmethod:itiscalledwithasliceobject, instead of a simple integer index, and slice objects may be passed on or inspected as needed. In Python 2.X, \_\_getslice\_\_ (defunct in 3.X) may be used for two-limit slices as well.
92
How can you catch in-place addition in a class?
In-place addition tries \_\_iadd\_\_ first, and \_\_add\_\_ with an assignment second. The same pattern holds true for all binary operators. The \_\_radd\_\_ method is also avail- able for right-side addition.
93
When should you provide operator overloading?
When a class naturally matches, or needs to emulate, a built-in typeÕs interfaces. For example, collections might imitate sequence or mapping interfaces, and call- ables might be coded for use with an API that expects a function. You generally shouldnÕt implement expression operators if they donÕt naturally map to your ob- jects naturally and logically, thoughÑuse normally named methods instead.
94
WhenwefetchaManagerobjectfromtheshelveandprintit,wheredoesthedisplay format logic come from?
In the final version of our classes, Manager ultimately inherits its \_\_repr\_\_ printing method from AttrDisplay in the separate classtools module and two levels up in the class tree. Manager doesnÕt have one itself, so the inheritance search climbs to its Person superclass; because there is no \_\_repr\_\_ there either, the search climbs higher and finds it in AttrDisplay. The class names listed in parentheses in a class statementÕs header line provide the links to higher superclasses.
95
When we fetch a Person object from a shelve without importing its module, how does the object know that it has a giveRaise method that we can call?
Shelves (really, the pickle module they use) automatically relink an instance to the class it was created from when that instance is later loaded back into memory. Python reimports the class from its module internally, creates an instance with its stored attributes, and sets the instanceÕs \_\_class\_\_ link to point to its original class. This way, loaded instances automatically obtain all their original methods (like lastName, giveRaise, and \_\_repr\_\_), even if we have not imported the instanceÕs class into our scope.
96
Why is it so important to move processing into methods, instead of hardcoding it outside the class?
ItÕs important to move processing into methods so that there is only one copy to change in the future, and so that the methods can be run on any instance. This is PythonÕs notion of encapsulationÑwrapping up logic behind interfaces, to better support future code maintenance. If you donÕt do so, you create code redundancy that can multiply your work effort as the code evolves in the future.
97
Why is it better to customize by subclassing rather than copying the original and modifying?
Customizing with subclasses reduces development effort. In OOP, we code by customizing what has already been done, rather than copying or changing existing code. This is the real Òbig ideaÓ in OOPÑbecause we can easily extend our prior work by coding new subclasses, we can leverage what weÕve already done. This is much better than either starting from scratch each time, or introducing multiple redundant copies of code that may all have to be updated in the future.
98
Why is it better to call back to a superclass method to run default actions, instead of copying and modifying its code in a subclass?
Copying and modifying code doubles your potential work effort in the future, re- gardless of the context. If a subclass needs to perform default actions coded in a superclass method, itÕs much better to call back to the original through the super- classÕs name than to copy its code. This also holds true for superclass constructors. Again, copying code creates redundancy, which is a major issue as code evolves.
99
Why is it better to use tools like \_\_dict\_\_ that allow objects to be processed ge- nerically than to write more custom code for each type of class?
Generic tools can avoid hardcoded solutions that must be kept in sync with the rest of the class as it evolves over time. A generic \_\_repr\_\_ print method, for ex- ample, need not be updated each time a new attribute is added to instances in an \_\_init\_\_ constructor. In addition, a generic print method inherited by all classes appears and need be modified in only one placeÑchanges in the generic version are picked up by all classes that inherit from the generic class. Again, eliminating code redundancy cuts future development effort; thatÕs one of the primary assets classes bring to the table.
100
Ingeneralterms,whenmightyouchoosetouseobjectembeddingandcomposition instead of inheritance?
Inheritance is best at coding extensions based on direct customization (like our Manager specialization of Person). Composition is well suited to scenarios where multiple objects are aggregated into a whole and directed by a controller layer class. Inheritance passes calls up to reuse, and composition passes down to delegate. Inheritance and composition are not mutually exclusive; often, the objects em- bedded in a controller are themselves customizations based upon inheritance.
101
What would you have to change if the objects coded in this chapter used a dictio- nary for names and a list for jobs, as in similar examples earlier in this book?
Not much since this was really a first-cut prototype, but the lastName method would need to be updated for the new name format; the Person constructor would have change the job default to an empty list; and the Manager class would probably need to pass along a job list in its constructor instead of a single string (self-test code would change as well, of course). The good news is that these changes would need to be made in just one placeÑin our classes, where such details are encap- sulated. The database scripts should work as is, as shelves support arbitrarily nes- ted data.
102
Howmightyoumodifytheclassesinthischaptertoimplementapersonalcontacts database in Python?
The classes in this chapter could be used as boilerplate ÒtemplateÓ code to imple- ment a variety of types of databases. Essentially, you can repurpose them by mod- ifying the constructors to record different attributes and providing whatever meth- ods are appropriate for the target application. For instance, you might use at- tributes such as name, address, birthday, phone, email, and so on for a contacts database, and methods appropriate for this purpose. A method named sendmail, for example, might use PythonÕs standard library smptlib module to send an email to one of the contacts automatically when called (see PythonÕs manuals or appli- cation-level books for more details on such tools). The AttrDisplay tool we wrote here could be used verbatim to print your objects, because it is intentionally generic. Most of the shelve database code here can be used to store your objects, too, with minor changes.
103
What three things are required in a C-like language but omitted in Python?
C-like languages require parentheses around the tests in some statements, semi- colons at the end of each statement, and braces around a nested block of code.
104
How is a statement normally terminated in Python?
The end of a line terminates the statement that appears on that line. Alternatively, if more than one statement appears on the same line, they can be terminated with semicolons; similarly, if a statement spans many lines, you must terminate it by closing a bracketed syntactic pair.
105
How are the statements in a nested block of code normally associated in Python?
Thestatementsinanestedblockareallindentedthesamenumberoftabsorspaces.
106
How can you make a single statement span multiple lines?
You can make a statement span many lines by enclosing part of it in parentheses, square brackets, or curly braces; the statement ends when Python sees a line that contains the closing part of the pair.
107
How can you code a compound statement on a single line?
Thebodyofacompoundstatementcanbemovedtotheheaderlineafterthecolon, but only if the body consists of only noncompound statements.
108
Is there any valid reason to type a semicolon at the end of a statement in Python?
Onlywhenyouneedtosqueezemorethanonestatementontoasinglelineofcode. Even then, this only works if all the statements are noncompound, and itÕs dis- couraged because it can lead to code that is difficult to read.
109
What is a try statement for?
The try statement is used to catch and recover from exceptions (errors) in a Python script. ItÕs usually an alternative to manually checking for errors in your code.
110
What is the most common coding mistake among Python beginners?
Forgetting to type the colon character at the end of the header line in a compound statement is the most common beginnerÕs mistake. If youÕre new to Python and havenÕt made it yet, you probably will soon!
111
What is significant about variables at the top level of a module whose names begin with a single underscore?
Variables at the top level of a module whose names begin with a single underscore arenotcopiedouttotheimportingscopewhenthefrom \*statementformisused. They can still be accessed by an import or the normal from statement form, though. The \_\_all\_\_ list is similar, but the logical converse; its contents are the only names that are copied out on a from \*.
112
What does it mean when a moduleÕs \_\_name\_\_ variable is the string "\_\_main\_\_"?
If a moduleÕs \_\_name\_\_ variable is the string "\_\_main\_\_", it means that the file is being executed as a top-level script instead of being imported from another file in the program. That is, the file is being used as a program, not a library. This usage mode variable supports dual-mode code and tests.
113
If the user interactively types the name of a module to test, how can your code import it?
User input usually comes into a script as a string; to import the referenced module given its string name, you can build and run an import statement with exec, or pass the string name in a call to the \_\_import\_\_ or importlib.import\_module.
114
How is changing sys.path different from setting PYTHONPATH to modify the module search path?
Changing sys.path only affects one running program (process), and is temporary Ñthe change goes away when the program ends. PYTHONPATH settings live in the operating systemÑthey are picked up globally by all your programs on a machine, and changes to these settings endure after programs exit.
115
If the module \_\_future\_\_ allows us to import from the future, can we also import from the past?
No, we canÕt import from the past in Python. We can install (or stubbornly use) an older version of the language, but the latest Python is generally the best Python (at least within linesÑsee 2.X longevity!).
116
What is the main point of OOP in Python?
OOP is about code reuseÑyou factor code to minimize redundancy and program by customizing what already exists instead of changing code in place or starting from scratch.
117
Where does an inheritance search look for an attribute?
An inheritance search looks for an attribute first in the instance object, then in the class the instance was created from, then in all higher superclasses, progressing from the bottom to the top of the object tree, and from left to right (by default). The search stops at the first place the attribute is found. Because the lowest version of a name found along the way wins, class hierarchies naturally support customi- zation by extension in new subclasses.
118
What is the difference between a class object and an instance object?
Both class and instance objects are namespaces (packages of variables that appear as attributes). The main difference between them is that classes are a kind of factory for creating multiple instances. Classes also support operator overloading meth- ods, which instances inherit, and treat any functions nested in the class as methods for processing instances.
119
Why is the first argument in a classÕs method function special?
The first argument in a classÕs method function is special because it always receives the instance object that is the implied subject of the method call. ItÕs usually called self by convention. Because method functions always have this implied subject and object context by default, we say they are Òobject-orientedÓ (i.e., designed to process or change objects).
120
What is the \_\_init\_\_ method used for?
If the \_\_init\_\_ method is coded or inherited in a class, Python calls it automatically each time an instance of that class is created. ItÕs known as the constructor method; it is passed the new instance implicitly, as well as any arguments passed explicitly to the class name. ItÕs also the most commonly used operator overloading method. If no \_\_init\_\_ method is present, instances simply begin life as empty namespaces.
121
How do you create a class instance?
You create a class instance by calling the class name as though it were a function; any arguments passed into the class name show up as arguments two and beyond in the \_\_init\_\_ constructor method. The new instance remembers the class it was created from for inheritance purposes.
122
How do you create a class?
You create a class by running a class statement; like function definitions, these statements normally run when the enclosing module file is imported (more on this in the next chapter).
123
How do you specify a classÕs superclasses?
You specify a classÕs superclasses by listing them in parentheses in the class state- ment, after the new classÕs name. The left-to-right order in which the classes are listed in the parentheses gives the left-to-right inheritance search order in the class tree.
124
Name three ways that you can assign three variables to the same value.
You can use multiple-target assignments (A = B = C = 0), sequence assignment (A, B, C = 0, 0, 0), or multiple assignment statements on three separate lines (A = 0,B = 0,andC = 0).Withthelattertechnique,asintroducedinChapter10,you can also string the three separate statements together on the same line by separating them with semicolons (A = 0; B = 0; C = 0).
125
Why might you need to care when assigning three variables to a mutable object?
If you assign them this way: A = B = C = [] all three names reference the same object, so changing it in place from one (e.g., A.append(99)) will affect the others. This is true only for in-place changes to mu- table objects like lists and dictionaries; for immutable objects such as numbers and strings, this issue is irrelevant.
126
WhatÕs wrong with saying L = L.sort()?
Thelistsortmethodislikeappendinthatitmakesanin-placechangetothesubject listÑit returns None, not the list it changes. The assignment back to L sets L to None, not to the sorted list. As discussed both earlier and later in this book (e.g., Chapter 8), a newer built-in function, sorted, sorts any sequence and returns a new list with the sorting result; because this is not an in-place change, its result can be meaningfully assigned to a name.
127
How might you use the print operation to send text to an external file?
To print to a file for a single print operation, you can use 3.XÕs print(X, file=F) call form, use 2.XÕs extended print \>\> file, X statement form, or assign sys.stdout to a manually opened file before the print and restore the original after. You can also redirect all of a programÕs printed text to a file with special syntax in the system shell, but this is outside PythonÕs scope.
128
Name four of PythonÕs core data types.
Numbers, strings, lists, dictionaries, tuples, files, and sets are generally considered to be the core object (data) types. Types, None, and Booleans are sometimes clas- sified this way as well. There are multiple number types (integer, floating point, complex, fraction, and decimal) and multiple string types (simple strings and Uni- code strings in Python 2.X, and text strings and byte strings in Python 3.X).
129
Why are they called ÒcoreÓ data types?
They are known as ÒcoreÓ types because they are part of the Python language itself and are always available; to create other objects, you generally must call functions in imported modules. Most of the core types have specific syntax for generating the objects: 'spam', for example, is an expression that makes a string and deter- mines the set of operations that can be applied to it. Because of this, core types are hardwired into PythonÕs syntax. In contrast, you must call the built-in open function to create a file object (even though this is usually considered a core type too).
130
What does ÒimmutableÓ mean, and which three of PythonÕs core types are con- sidered immutable?
An ÒimmutableÓ object is an object that cannot be changed after it is created. Numbers, strings, and tuples in Python fall into this category. While you cannot change an immutable object in place, you can always make a new one by running an expression. Bytearrays in recent Pythons offer mutability for text, but they are not normal strings, and only apply directly to text if itÕs a simple 8-bit kind (e.g., ASCII).
131
What does ÒsequenceÓ mean, and which three types fall into that category?
AÒsequenceÓisapositionallyorderedcollectionofobjects.Strings,lists,andtuples are all sequences in Python. They share common sequence operations, such as indexing, concatenation, and slicing, but also have type-specific method calls. A related term, Òiterable,Ó means either a physical sequence, or a virtual one that produces its items on request.
132
What does ÒmappingÓ mean, and which core type is a mapping?
The term ÒmappingÓ denotes an object that maps keys to associated values. PythonÕs dictionary is the only mapping type in the core type set. Mappings do not maintain any left-to-right positional ordering; they support access to data stored by key, plus type-specific method calls.
133
What is Òpolymorphism,Ó and why should you care?
ÒPolymorphismÓ means that the meaning of an operation (like a +) depends on the objects being operated on. This turns out to be a key idea (perhaps the key idea) behind using Python wellÑnot constraining code to specific types makes that code automatically applicable to many types.
134
How are lambda expressions and def statements related?
Both lambda and def create function objects to be called later. Because lambda is an expression, though, it returns a function object instead of assigning it to a name, and it can be used to nest a function definition in places where a def will not work syntactically. A lambda allows for only a single implicit return value expression, though; because it does not support a block of statements, it is not ideal for larger functions.
135
WhatÕs the point of using lambda?
lambdas allow us to ÒinlineÓ small units of executable code, defer its execution, and provide it with state in the form of default arguments and enclosing scope variables. Using a lambda is never required; you can always code a def instead and reference the function by name. lambdas come in handy, though, to embed small pieces of deferred code that are unlikely to be used elsewhere in a program. They commonly appear in callback-based programs such as GUIs, and they have a natural affinity with functional tools like map and filter that expect a processing function.
136
Compare and contrast map, filter, and reduce.
These three built-in functions all apply another function to items in a sequence (or other iterable) object and collect results. map passes each item to the function and collects all results, filter collects items for which the function returns a True value, and reduce computes a single value by applying the function to an accumulator and successive items. Unlike the other two, reduce is available in the functools module in 3.X, not the built-in scope; reduce is a built-in in 2.X.
137
What are function annotations, and how are they used?
Functionannotations,availablein3.X(3.0andlater),aresyntacticembellishments of a functionÕs arguments and result, which are collected into a dictionary assigned to the functionÕs \_\_annotations\_\_ attribute. Python places no semantic meaning on these annotations, but simply packages them for potential use by other tools.
138
What are recursive functions, and how are they used?
Recursive functions call themselves either directly or indirectly in order to loop. They may be used to traverse arbitrarily shaped structures, but they can also be used for iteration in general (though the latter role is often more simply and effi- ciently coded with looping statements). Recursion can often be simulated or re- placed by code that uses explicit stacks or queues to have more control over tra- versals.
139
What are some general design guidelines for coding functions?
Functions should generally be small and as self-contained as possible, have a single unified purpose, and communicate with other components through input argu- ments and return values. They may use mutable arguments to communicate results too if changes are expected, and some types of programs imply other communi- cation mechanisms.
140
Name three or more ways that functions can communicate results to a caller.
Functions can send back results with return statements, by changing passed-in mutable arguments, and by setting global variables. Globals are generally frowned upon (except for very special cases, like multithreaded programs) because they can make code more difficult to understand and use. return statements are usually best, but changing mutables is fine (and even useful), if expected. Functions may also communicate results with system devices such as files and sockets, but these are beyond our scope here.
141
Consider the following three statements. Do they change the value printed for A? A = "spam" B= A B = "shrubbery"
No: A still prints as "spam". When B is assigned to the string "shrubbery", all that happens is that the variable B is reset to point to the new string object. A and B initially share (i.e., reference/point to) the same single string object "spam", but two names are never linked together in Python. Thus, setting B to a different object has no effect on A. The same would be true if the last statement here were B = B + 'shrubbery', by the wayÑthe concatenation would make a new object for its result, which would then be assigned to B only. We can never overwrite a string (or num- ber, or tuple) in place, because strings are immutable.
142
Consider these three statements. Do they change the printed value of A? A = ["spam"] B= A B[0] = "shrubbery"
Yes: A now prints as ["shrubbery"]. Technically, we havenÕt really changed either A or B; instead, weÕve changed part of the object they both reference (point to) by overwriting that object in place through the variable B. Because A references the same object as B, the update is reflected in A as well.
143
How about theseÑis A changed now? A = ["spam"] B = A[:] B[0] = "shrubbery"
No: A still prints as ["spam"]. The in-place assignment through B has no effect this time because the slice expression made a copy of the list object before it was as- signed to B. After the second assignment statement, there are two different list objects that have the same value (in Python, we say they are ==, but not is). The third statement changes the value of the list object pointed to by B, but not that pointed to by A.
144
What are the two new constraints on user-defined exceptions in Python 3.X?
In 3.X, exceptions must be defined by classes (that is, a class instance object is raised and caught). In addition, exception classes must be derived from the built- in class BaseException; most programs inherit from its Exception subclass, to sup- port catchall handlers for normal kinds of exceptions.
145
How are raised class-based exceptions matched to handlers?
Class-based exceptions match by superclass relationships: naming a superclass in an exception handler will catch instances of that class, as well as instances of any of its subclasses lower in the class tree. Because of this, you can think of superclasses as general exception categories and subclasses as more specific types of exceptions within those categories.
146
Name two ways that you can attach context information to exception objects.
Youcanattachcontextinformationtoclass-basedexceptionsbyfillingoutinstance attributes in the instance object raised, usually in a custom class constructor. For simpler needs, built-in exception superclasses provide a constructor that stores its arguments on the instance automatically (as a tuple in the attribute args). In ex- ception handlers, you list a variable to be assigned to the raised instance, then go through this name to access attached state information and call any methods de- fined in the class.
147
Name two ways that you can specify the error message text for exception objects.
The error message text in class-based exceptions can be specified with a custom \_\_str\_\_ operator overloading method. For simpler needs, built-in exception su- perclasses automatically display anything you pass to the class constructor. Oper- ations like print and str automatically fetch the display string of an exception object when it is printed either explicitly or as part of an error message.
148
Why should you not use string-based exceptions anymore today?
Because Guido said soÑthey have been removed as of both Python 2.6 and 3.0. There are arguably good reasons for this: string-based exceptions did not support categories, state information, or behavior inheritance in the way class-based ex- ceptions do. In practice, this made string-based exceptions easier to use at first when programs were small, but more complex to use as programs grew larger. The downsides of requiring exceptions to be classes are to break existing code, and create a forward knowledge dependencyÑbeginners must first learn classes and OOP before they can code new exceptions, or even truly understand exceptions at all. In fact, this is why this relatively straightforward topic was largely postponed until this point in the book. For better or worse, such dependencies are not un- common in Python today (see the preface and conclusion for more on such things).
149
What is the purpose of an \_\_init\_\_.py file in a module package directory?
The \_\_init\_\_.py file serves to declare and initialize a regular module package; Python automatically runs its code the first time you import through a directory in a process. Its assigned variables become the attributes of the module object created in memory to correspond to that directory. It is also not optional until 3.3 and laterÑyou canÕt import through a directory with package syntax unless it contains this file.
150
How can you avoid repeating the full package path every time you reference a packageÕs content?
Use the from statement with a package to copy names out of the package directly, or use the as extension with the import statement to rename the path to a shorter synonym. In both cases, the path is listed in only one place, in the from or import statement.
151
Which directories require \_\_init\_\_.py files?
In Python 3.2 and earlier, each directory listed in an executed import or from state- ment must contain an \_\_init\_\_.py file. Other directories, including the directory that contains the leftmost component of a package path, do not need to include this file.
152
When must you use import instead of from with packages?
You must use import instead of from with packages only if you need to access the same name defined in more than one path. With import, the path makes the ref- erences unique, but from allows only one version of any given name (unless you also use the as extension to rename).
153
What is the difference between from mypkg import spam and from . import spam?
In Python 3.X, from mypkg import spam is an absolute importÑthe search for mypkg skips the package directory and the module is located in an absolute directory insys.path.Astatementfrom . import spam,ontheotherhand,isarelativeimport Ñspam is looked up relative to the package in which this statement is contained only. In Python 2.X, the absolute import searches the package directory first before proceeding to sys.path; relative imports work as described.
154
What is a namespace package?
A namespace package is an extension to the import model, available in Python 3.3 and later, that corresponds to one or more directories that do not have \_\_init\_\_.py files. When Python finds these during an import search, and does not find a simple module or regular package first, it creates a namespace package that is the virtual concatenation of all found directories having the requested module name. Further nested components are looked up in all the namespace packageÕs directories. The effect is similar to a regular package, but content may be split across multiple directories.
155
Can the string find method be used to search a list?
No, because methods are always type-specific; that is, they only work on a single data type. Expressions like X+Y and built-in functions like len(X) are generic, though, and may work on a variety of types. In this case, for instance, the in mem- bership expression has a similar effect as the string find, but it can be used to search both strings and lists. In Python 3.X, there is some attempt to group methods by categories (for example, the mutable sequence types list and bytearray have sim- ilar method sets), but methods are still more type-specific than other operation sets.
156
Can a string slice expression be used on a list?
Yes.Unlikemethods,expressionsaregenericandapplytomanytypes.Inthiscase, the slice expression is really a sequence operationÑit works on any type of sequence object, including strings, lists, and tuples. The only difference is that when you slice a list, you get back a new list.
157
How would you convert a character to its ASCII integer code? How would you convert the other way, from an integer to a character?
The built-in ord(S) function converts from a one-character string to an integer character code; chr(I) converts from the integer code back to a string. Keep in mind, though, that these integers are only ASCII codes for text whose characters are drawn only from ASCII character set. In the Unicode model, text strings are really sequences of Unicode code point identifying integers, which may fall outside the 7-bit range of numbers reserved by ASCII (more on Unicode in Chapter 4 and Chapter 37).
158
How might you go about changing a string in Python?
Stringscannotbechanged;theyareimmutable.However,youcanachieveasimilar effect by creating a new stringÑby concatenating, slicing, running formatting ex- pressions, or using a method call like replaceÑand then assigning the result back to the original variable name.
159
Given a string S with the value "s,pa,m", name two ways to extract the two char- acters in the middle.
You can slice the string using S[2:4], or split on the comma and index the string using S.split(',')[1]. Try these interactively to see for yourself.
160
How many characters are there in the string "a\nb\x1f\000d"?
Six. The string "a\nb\x1f\000d" contains the characters a, newline (\n), b, binary 31 (a hex escape \x1f), binary 0 (an octal escape \000), and d. Pass the string to the built-in len function to verify this, and print each of its characterÕs ord results to see the actual code point (identifying number) values. See Table 7-2 for more details on escapes.
161
Why might you use the string module instead of string method calls?
Youshouldneverusethestringmoduleinsteadofstringobjectmethodcallstoday ÑitÕs deprecated, and its calls are removed completely in Python 3.X. The only valid reason for using the string module at all today is for its other tools, such as predefined constants. You might also see it appear in what is now very old and dusty Python code (and books of the misty pastÑlike the 1990s).
162
How do you make a module?
Tocreateamodule,yousimplywriteatextfilecontainingPythonstatements;every source code file is automatically a module, and there is no syntax for declaring one. Import operations load module files into module objects in memory. You can also make a module by writing code in an external language like C or Java, but such extension modules are beyond the scope of this book.
163
How is the from statement related to the import statement?
The from statement imports an entire module, like the import statement, but as an extra step it also copies one or more variables from the imported module into the scope where the from appears. This enables you to use the imported names directly (name) instead of having to go through the module (module.name).
164
How is the reload function related to imports?
By default, a module is imported only once per process. The reload function forces a module to be imported again. It is mostly used to pick up new versions of a moduleÕs source code during development, and in dynamic customization scenar- ios.
165
When must you use import instead of from?
You must use import instead of from only when you need to access the same name in two different modules; because youÕll have to specify the names of the enclosing modules, the two names will be unique. The as extension can render from usable in this context as well.
166
Name three potential pitfalls of the from statement.
The from statement can obscure the meaning of a variable (which module it is defined in), can have problems with the reload call (names may reference prior versions of objects), and can corrupt namespaces (it might silently overwrite names you are using in your scope). The from \* form is worse in most regardsÑit can seriously corrupt namespaces and obscure the meaning of variables, so it is prob- ably best used sparingly.
167
What...is the airspeed velocity of an unladen swallow?
6. What do you mean? An African or European swallow?
168
What is the try statement for?
The try statement catches and recovers from exceptionsÑit specifies a block of code to run, and one or more handlers for exceptions that may be raised during the blockÕs execution.
169
What are the two common variations of the try statement?
Thetwocommonvariationsonthetrystatementaretry/except/else(forcatching exceptions) and try/finally (for specifying cleanup actions that must occur whether an exception is raised or not). Through Python 2.4, these were separate statements that could be combined by syntactic nesting; in 2.5 and later, except and finally blocks may be mixed in the same statement, so the two statement forms are merged. In the merged form, the finally is still run on the way out of the try, regardless of what exceptions may have been raised or handled. In fact, the merged form is equivalent to nesting a try/except/else in a try/finally, and the two still have logically distinct roles.
170
What is the raise statement for?
The raise statement raises (triggers) an exception. Python raises built-in excep- tions on errors internally, but your scripts can trigger built-in or user-defined ex- ceptions with raise, too.
171
What is the assert statement designed to do, and what other statement is it like?
The assert statement raises an AssertionError exception if a condition is false. It works like a conditional raise statement wrapped up in an if statement, and can be disabled with a ÐO switch.
172
What is the with/as statement designed to do, and what other statement is it like?
The with/as statement is designed to automate startup and termination activities that must occur around a block of code. It is roughly like a try/finally statement in that its exit actions run whether an exception occurred or not, but it allows a richer object-based protocol for specifying entry and exit actions, and may reduce code size. Still, itÕs not quite as general, as it applies only to objects that support its protocol; try handles many more use cases.
173
What is the output of the following code, and why? \>\>\> def func(a, b=4, c=5): print(a, b, c) \>\>\> func(1, 2)
The output here is 1 2 5, because 1 and 2 are passed to a and b by position, and c is omitted in the call and defaults to
174
What is the output of this code, and why? \>\>\> def func(a, b, c=5): print(a, b, c) \>\>\> func(1, c=3, b=2)
The output this time is 1 2 3: 1 is passed to a by position, and b and c are passed 2 and 3 by name (the left-to-right order doesnÕt matter when keyword arguments are used like this).
175
How about this code: what is its output, and why? \>\>\> def func(a, \*pargs): print(a, pargs) \>\>\> func(1, 2, 3)
This code prints 1 (2, 3), because 1 is passed to a and the \*pargs collects the remaining positional arguments into a new tuple object. We can step through the extra positional arguments tuple with any iteration tool (e.g., for arg in pargs: ...).
176
What does this code print, and why? \>\>\> def func(a, \*\*kargs): print(a, kargs) \>\>\> func(a=1, c=3, b=2)
This time the code prints 1 {'b': 2, 'c': 3}, because 1 is passed to a by name and the \*\*kargs collects the remaining keyword arguments into a dictionary. We could step through the extra keyword arguments dictionary by key with any iter- ation tool (e.g., for key in kargs: ...). Note that the order of the dictionaryÕs keys may vary per Python and other variables.
177
What gets printed by this, and why? \>\>\> def func(a, b, c=3, d=4): print(a, b, c, d) \>\>\> func(1, \*(5, 6))
The output here is 1 5 6 4: the 1 matches a by position, 5 and 6 match b and c by \*name positionals (6 overrides cÕs default), and d defaults to 4 because it was not passed a value.
178
One last time: what is the output of this code, and why? \>\>\> def func(a, b, c): a = 2; b[0] = 'x'; c['a'] = 'y' \>\>\> l=1; m=[1]; n={'a':0} \>\>\> func(l, m, n) \>\>\> l, m, n
Thisdisplays(1, ['x'], {'a': 'y'})ÑthefirstassignmentinthefunctiondoesnÕt impact the caller, but the second two do because they change passed-in mutable objects in place.
179
What is the output of the following code, and why? "\>\>\> X = 'Spam' \>\>\> def func(): " \>\>\> print(X) \>\>\> func()
The output here is 'Spam', because the function references a global variable in the enclosing module (because it is not assigned in the function, it is considered global).
180
What is the output of this code, and why? \>\>\> X = 'Spam' \>\>\> def func(): X = 'NI!' \>\>\> func() \>\>\> print(X)
The output here is 'Spam' again because assigning the variable inside the function makes it a local and effectively hides the global of the same name. The print state- ment finds the variable unchanged in the global (module) scope.
181
What does this code print, and why? \>\>\> X = 'Spam' \>\>\> def func(): X = 'NI' print(X) \>\>\> func() \>\>\> print(X)
It prints 'NI' on one line and 'Spam' on another, because the reference to the vari- able within the function finds the assigned local and the reference in the print statement finds the global.
182
What output does this code produce? Why? \>\>\> X = 'Spam' \>\>\> def func(): global X X = 'NI' \>\>\> func() \>\>\> print(X)
This time it just prints 'NI' because the global declaration forces the variable as- signed inside the function to refer to the variable in the enclosing global scope.
183
What about this codeÑwhatÕs the output, and why? \>\>\> X = 'Spam' \>\>\> def func(): X = 'NI' def nested(): print(X) nested() \>\>\> func() \>\>\> X
The output in this case is again 'NI' on one line and 'Spam' on another, because the print statement in the nested function finds the name in the enclosing func- tionÕs local scope, and the print at the end finds the variable in the global scope.
184
How about this example: what is its output in Python 3.X, and why? \>\>\> def func(): X = 'NI' def nested(): nonlocal X X = 'Spam' nested() print(X) \>\>\> func()
This example prints 'Spam', because the nonlocal statement (available in Python 3.X but not 2.X) means that the assignment to X inside the nested function changes X in the enclosing functionÕs local scope. Without this statement, this assignment would classify X as local to the nested function, making it a different variable; the code would then print 'NI' instead.
185
Name three or more ways to retain state information in a Python function.
Although the values of local variables go away when a function returns, you can make a Python function retain state information by using shared global variables, enclosing function scope references within nested functions, or using default ar- gument values. Function attributes can sometimes allow state to be attached to the function itself, instead of looked up in scopes. Another alternative, using classes and OOP, sometimes supports state retention better than any of the scope-based techniques because it makes it explicit with attribute assignments; weÕll explore this option in Part VI.