DekGenius.com
[ Team LiB ] Previous Section Next Section

8.1 Assignment Statements

We've been using the Python assignment statement already, to assign objects to names. In its basic form, you write a target of an assignment on the left of an equals sign and an object to be assigned on the right. The target on the left may be a name or object component, and the object on the right can be an arbitrary expression that computes an object. For the most part, assignment is straightforward to use, but here are a few properties to keep in mind:

  • Assignments create object references. Python assignment stores references to objects in names or data structure slots. It always creates references to objects, instead of copying objects. Because of that, Python variables are much more like pointers than data storage areas.

  • Names are created when first assigned. Python creates variable names the first time you assign them a value (an object reference). There's no need to predeclare names ahead of time. Some (but not all) data structure slots are created when assigned too (e.g., dictionary entries, some object attributes). Once assigned, a name is replaced by the value it references whenever it appears in an expression.

  • Names must be assigned before being referenced. Conversely, it's an error to use a name you haven't assigned a value to yet. Python raises an exception if you try, rather than returning some sort of ambiguous (and hard to notice) default value.

  • Implicit assignments: import, from, def, class, for, function arguments. In this section, we're concerned with the = statement, but assignment occurs in many contexts in Python. For instance, we'll see later that module imports, function and class definitions, for loop variables, and function arguments, are all implicit assignments. Since assignment works the same everywhere it pops up, all these contexts simply bind names to object references at runtime.

Table 8-2 illustrates the different assignment statements in Python. In addition to this table, Python includes a set of assignment statement forms known as augmented assignment.

Table 8-2. Assignment statement forms

Operation

Interpretation

spam = 'Spam'

Basic form

spam, ham = 'yum', 'YUM'

Tuple assignment (positional)

[spam, ham] = ['yum', 'YUM']

List assignment (positional)

spam = ham = 'lunch'

Multiple-target

The first line in Table 8-2 is by far the most common: binding a single object to a name (or data-structure slot). The other table entries represent special forms:


Tuple and list unpacking assignments

The second and third lines are related. When you code tuples or lists on the left side of the =, Python pairs objects on the right side with targets on the left and assigns them from left to right. For example, in the second line of the table, name spam is assigned the string 'yum', and name ham is bound to string 'YUM'. Internally, Python makes a tuple of the items on the right first, so this is often called tuple (and list) unpacking assignment.


Multiple-target assignments

The last line in Table 8-2 shows the multiple-target form of assignment. In this form, Python assigns a reference to the same object (the object farthest to the right) to all the targets on the left. In the table, names spam and ham would both be assigned a reference to the same string object 'lunch', and so share the same reference to the object. The effect is the same as if you had coded ham='lunch', followed by spam=ham, since ham evaluates to the original string object.

We've already used basic assignment. Here are a few simple examples of unpacking assignment in action:

% python 
>>> nudge = 1
>>> wink  = 2
>>> A, B = nudge, wink             # Tuple assignment
>>> A, B                           # Like A = nudge; B = wink
(1, 2)
>>> [C, D] = [nudge, wink]         # List assignment
>>> C, D
(1, 2)

Tuple assignment leads to a common coding trick in Python that was introduced in a solution to the exercises from Part II. Since Python creates a temporary tuple that saves the values on the right, unpacking assignments are also a way to swap two variables' values without creating a temporary of your own:

>>> nudge = 1
>>> wink  = 2
>>> nudge, wink = wink, nudge      # Tuples: swaps values
>>> nudge, wink                    # Like T = nudge; nudge = wink; wink = T
(2, 1)

The tuple and list assignment forms are generalized to accept any type of sequence on the right, as long as it is of the same length. You can assign a tuple of values to a list of variables, a string of characters to a tuple of variables, and so on. In all cases, Python assigns items in the sequence on the right to variables in the sequence on the left by position, from left to right:

>>> [a, b, c] = (1, 2, 3)
>>> a, c
(1, 3)
>>> (a, b, c) = "ABC"
>>> a, c
('A', 'C')

Unpacking assignment also gives rise to another common coding idiom in Python: assigning an integer series to a set of variables:

>>> red, green, blue = range(3)
>>> red, blue
(0, 2)

This initializes the three names to integer codes 0, 1, and 2, respectively (it's Python's equivalent of enumerated data types you may have seen in other languages). To make sense of this, you also need to know that the range built-in function generates a list of successive integers:

>>> range(3)
[0, 1, 2]

Since range is commonly used in for loops, we'll say more about it in Chapter 10.

8.1.1 Variable Name Rules

Now that we've seen assignment statements, it is also time to get more formal in the use of variable names. In Python, names come into existence when you assign values to them, but there are a few rules to follow when picking names for things in our program:


Syntax: (underscore or letter) + (any number of letters, digits, or underscores)

Variable names must start with an underscore or letter, and be followed by any number of letters, digits, or underscores. _spam, spam, and Spam_1 are legal names, but 1_Spam, spam$, and @#! are not.


Case matters: SPAM is not the same as spam

Python always pays attention to case in programs, both in names you create and in reserved words. For instance, names X and x refer to two different variables.


Reserved words are off limits

Names we define cannot be the same as words that mean special things in the Python language. For instance, if we try to use a variable name like class, Python will raise a syntax error, but klass and Class work fine. Table 8-3 lists the words that are reserved (and hence off limits) in Python.

Table 8-3. Python reserved words
and
del
for
Is
raise
assert
elif
from
lamda
return
break
else
global
not
try
class
except
if
or
while
continue
exec
import
pass
yield[1]
def
finally
in
print
 

[1] yield is an optional extension in Version 2.2, but is a standard keyword in 2.3. It is used in conjunction with generator functions, a newer feature discussed in Chapter 14.

Python's reserved words are always all lowercase. And they are truly reserved; unlike names in the built-in scope that you will meet in the next part, you cannot redefine reserved words by assignment (e.g., and=1 is a syntax error).[2] Furthermore, because module names in import statements become variables in your script, this constraint extends to your module filenames—you can code a file called and.py, but cannot import it; we'll revisit this idea in Part V.

[2] In the Jython Java-based implementation or Python, though, user-defined variables can sometimes be the same as Python reserved words.

8.1.1.1 Naming conventions

Besides these rules, there is also a set of naming conventions—rules which are not required, but are used in normal practice. For instance, because names with two leading and trailing underscores (e.g., __name__) generally have special meaning to the Python interpreter, you should avoid this pattern for your own names. Here is a list of all the conventions Python follows:

  • Names that begin with a single underscore (_X) are not imported by a from module import * statement (described in Chapter 16).

  • Names that have two leading and trailing underscores (__X__) are system-defined names, which have special meaning to the interpreter.

  • Names that begin with two underscores and do not end with two more (__X) are localized ("mangled") to enclosing classes (described in Chapter 23).

  • The name that is just a single underscore (_) retains the result of the last expression, when working interactively.

In addition to these Python interpreter conventions, we'll meet other conventions that Python programmers usually follow as well. In Part VI, for instance, we'll see class names commonly start with an uppercase letter, and that the name self, though not reserved, usually has a special role. And in Part IV, we'll study another class of names known as the built-ins, which are predefined but not reserved (and so can be reassigned: open=42 works, though you might wish it didn't).

8.1.1.2 Names have no type, but objects do

It's crucial to keep Python's distinction between names and objects clear. As described in Section 4.6 in Chapter 4, objects have a type (e.g., integer, list), and may be mutable or not. Names (a.k.a. variables), on the other hand, are always just references to objects; they have no notion of mutability and have no associated type information, apart from the type of the object they happen to reference at a given point in time.

In fact, it's perfectly okay to assign the same name to different kinds of objects at different times:

>>> x = 0            # x bound to an integer object
>>> x = "Hello"      # Now it's a string.
>>> x = [1, 2, 3]    # And now it's a list.

In later examples, you'll see that this generic nature of names can be a decided advantage in Python programming.[3] In Part IV, you'll learn that names also live in something called a scope, which defines where they can be used; the place you assign a name determines where it is visible.

[3] If you've used C++, you may be interested to know that there is no notion of C++'s const declaration in Python; certain objects may be immutable, but names can always be assigned. Python also has ways to hide names in classes and modules, but they're not the same as C++'s declarations.

8.1.2 Augmented Assignment Statements

Beginning with Python 2.0, a set of additional assignment statement formats, listed in Table 8-4, are now available. Known as augmented assignment, and borrowed from the C language, these formats are mostly just shorthand. They imply the combination of a binary expression and an assignment. For instance, the following two formats are now roughly equivalent:

X = X + Y       # Traditional form
X += Y          # Newer augmented form

Table 8-4. Augmented assignment statements
X += Y
X &= Y
X -= Y
X |= Y
X *= Y
X ^= Y
X /= Y
X »= Y
X %= Y
X «= Y
X **= Y
X //= Y

Augmented assignment works on any type that supports the implied binary expression. For example, here are two ways to add 1 to a name:

>>> x = 1
>>> x = x + 1          # Traditional
>>> x
2
>>> x += 1             # Augmented
>>> x
3

When applied to a string, the augmented form performs concatenation instead—exactly as if you had typed the longer: S = S + "SPAM":

>>> S = "spam"
>>> S += "SPAM"        # Implied concatenation
>>> S
'spamSPAM'

As shown in Table 8-4, there are analogous augmented assignment forms for every Python binary expression operator (an operator with values on the left and right side). For instance, X*=Y multiplies and assigns, X>>=Y shifts right and assigns, and so on. X //= Y (for floor division) is new in Version 2.2. Augmented assignments have three advantages:[4]

[4] C/C++ programmers take note: although Python now has things like X+=Y, it still does not have C's auto-increment/decrement operators (e.g., X++, --X). These don't quite map to the Python object model, because there is no notion of an in-place change to immutable objects like numbers.

  • There's less for you to type. Need we say more?

  • They only need to evaluate the left side once. In X+=Y, X could be a complicated object expression. In the augmented form, it need only be evaluated once. In the long form, X=X+Y, X appears twice, and must be run twice.

  • They automatically choose the optimal technique. For objects that support in-place changes, the augmented forms automatically perform in-place change operations, instead of slower copies.

The last point here requires a bit more explanation. For augment assignments, in-place operations may be applied for mutable objects as an optimization. Recall that lists can be extended in a variety of ways. To add a single item to the end of a list, we can concatenate or append:

>>> L = [1, 2]
>>> L = L + [3]            # Concatenate: slower
>>> L
[1, 2, 3]
>>> L.append(4)            # Faster, but in-place
>>> L
[1, 2, 3, 4]

And to add a set of items at the end, we may either concatenate again, or call the list extend method:[5]

[5] As suggested in Chapter 6, we can also use slice assignment: L[len(L):] = [11,12,13], but this works roughly the same as the simpler list extend method.

>>> L = L + [5, 6]         # Concatenate: slower
>>> L
[1, 2, 3, 4, 5, 6]
>>> L.extend([7, 8])       # Faster, but in-place
>>> L
[1, 2, 3, 4, 5, 6, 7, 8]

In all of these, concatenation is less prone to the side effects of shared object references, but will generally run slower than the in-place equivalent. Concatenation must create a new object, copy in the list on the left, and then copy in the list on the right. By contrast, in-place method calls simply add items at the end of a memory block.

When augmented assignment is used to extend a list, we can forget these details—Python automatically calls the quicker extend method, instead of the slower concatenation operation implied by +:

>>> L += [9, 10]       # Mapped to L.extend([9, 10])
>>> L
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    [ Team LiB ] Previous Section Next Section