# Python Expressions and Operators

Expressions and Operators

An expression is a phrase of code that Python evaluates to produce a value. The simplest expressions are literals and identifiers. You build other expressions by joining subexpressions with the operators and/or delimiters in Table 4-2. This table lists operators in decreasing order of precedence, higher precedence before lower. Operators listed together have the same precedence. The third column lists the associativity of the operator: L (left-to-right), R (right-to-left), or NA (nonassociative).

Table 4-2. Operator precedence in expressions

Operator DescriptionAssociativity
`expr,…`String conversionNA
{key:expr,…}Dictionary creationNA
[expr,…]List creationNA
(expr,…)Tuple creation or just parenthesesNA
f(expr,…)Function callL
x[index:index]SlicingL
x[index]IndexingL
x.att r Attribute referenceL
x**y Exponentiation ( x to y th power)R
~x Bitwise NOTNA
+x , –x Unary plus and minusNA
x*y , x/y , x//y , x%y Multiplication, division, truncating division, remainderL
x<<y , x>>y Left-shift, right-shiftL
x&y Bitwise ANDL
x^y Bitwise XORL
x|y Bitwise ORL
x<y , x<=y , x>y , x y , x<<>>y ,Comparisons (less than, less than orNA
x!=y , x==y equal, greater than, greater than or equal, inequality, equality) a
x is y , x is not y Identity testsNA
x in y , x not in y Membership testsNA
not x Boolean NOTNA
x and y Boolean ANDL
x or y Boolean ORL
lambda arg,…: expr Anonymous simple functionNA

a <> and != are alternate forms of the same operator. != is the preferred version; <> is obsolete.

In Table 4-2, exprkey ,  findexx , and y indicate any expression, while attr and arg  indicate any identifier. The notation ,… means commas join zero or more repetitions, except for string conversion, where you need one or more repetitions.

A trailing comma is allowed and innocuous in all such cases, except for string conversion, where it’s forbidden. The string conversion operator, with its quirky behavior, is not recommended; use built-in function repr (covered in repr on page 166) instead.

Comparison Chaining

You can chain comparisons, implying a logical and. For example:

a < b <= c < d

has the same meaning as:

a < b and b <= c and c < d

The chained form is more readable and evaluates each subexpression once at the most.

Short-Circuiting Operators

Operators and and or short-circuit their operands’ evaluation: the righthand operand evaluates only if its value is needed to get the truth value of the entire and or or operation.

In other words, x  and y  first evaluates x. If x  is false, the result is x ; otherwise, the result is y. Similarly, x or y first evaluates x. If x  is true, the result is x ; otherwise, the result is y .

and and or don’t force their results to be True or False, but rather return one or the other of their operands. This lets you use these operators more generally, not just in Boolean contexts. and and or, because of their short-circuiting semantics, differ from all other operators, which fully evaluate all operands before performing the operation. and and or let the left operand act as a guard for the right operand.

{mospagebreak title=The Python 2.5 ternary operator}

Python 2.5 introduces another short-circuiting operator, the ternary operator if/else :

whentrue if condition else whenfalse

Each of whentrue , whenfalse , and condition  is an arbitrary expression. condition evaluates first. If condition  is true, the result is whentrue ; otherwise, the result is whenfalse . Only one of the two subexpressions whentrue  and whenfalse evaluates, depending on the truth value of condition.

The order of the three subexpressions in this new ternary operator may be a bit confusing. Also, a recommended style is to always place parentheses around the whole expression.

Numeric Operations

Python supplies the usual numeric operations, as we’ve just seen in Table 4-2. Numbers are immutable objects: when you perform numeric operations on number objects, you always produce a new number object and never modify existing ones. You can access the parts of a complex object z as read-only attributes z.real and z.imag. Trying to rebind these attributes on a complex object raises an exception.

A numbers optional + or sign, and the + that joins a floating-point literal to an imaginary one to make a complex number, are not part of the literals’ syntax. They are ordinary operators, subject to normal operator precedence rules (see Table 4-2). For example, -2**2 evaluates to -4: exponentiation has higher precedence than unary minus, so the whole expression parses as -(2**2), not as (-2)**2.

Numeric Conversions

You can perform arithmetic operations and comparisons between any two numbers of Python built-in types. If the operands’ types differ, coercion applies: Python converts the operand with the "smaller" type to the "larger" type. The types, in order from smallest to largest, are integers, long integers, floating-point numbers, and complex numbers.

You can request an explicit conversion by passing a noncomplex numeric argument to any of the built-in number types: int, long, float, and complex. int and long drop their argument’s fractional part, if any (e.g., int(9.8) is 9). You can also call complex with two numeric arguments, giving real and imaginary parts. You cannot convert a complex to another numeric type in this way, because there is no single unambiguous way to convert a complex number into, e.g., a float.

Each built-in numeric type can also take a string argument with the syntax of an appropriate numeric literal, with small extensions: the argument string may have leading and/or trailing whitespace, may start with a sign, and, for complex numbers, may sum or subtract a real part and an imaginary one. int and long can also be called with two arguments: the first one a string to convert, and the second the radix, an integer between 2 and 36 to use as the base for the conversion (e.g., int(‘101’, 2) returns 5, the value of ‘101’ in base 2).

{mospagebreak title=Arithmetic Operations}

Python arithmetic operations behave in rather obvious ways, with the possible exception of division and exponentiation.

Division

If the right operand of /, //, or % is 0, Python raises a runtime exception. The // operator performs truncating division, which means it returns an integer result (converted to the same type as the wider operand) and ignores the remainder, if any. When both operands are integers (plain or long), the / operator behaves like // if the switch -Qold was used on the Python command line (-Qold is the default in Python 2.3, 2.4, and 2.5). Otherwise, / performs true division, returning a floating-point result (or a complex result if either operand is a complex number). To have / perform true division on integer operands in Python 2.3, 2.4, or 2.5, use the switch -Qnew on the Python command line, or begin your source file with the statement:

from __future__ import division

This statement ensures that operator / (within the module that starts with this statement only) works without truncation on operands of any type.

To ensure that the behavior of division does not depend on the -Q switch, and on the exact version of Python you’re using, always use // when you want truncating division. When you do not want truncation, use /, but also ensure that at least one operand is not an integer. For example, instead of using just a/b, code 1.*a/b to avoid making any assumption on the types of a and b. To check whether your program has version dependencies in its use of division, use the switch -Qwarn on the Python command line to get runtime warnings about all uses of / on integer operands.

The built-in divmod function takes two numeric arguments and returns a pair whose items are the quotient and remainder, so you don’t have to use both // for the quotient and % for the remainder.

Exponentiation

The exponentiation ("raise to power") operation, a**b , raises an exception if a  is less than zero and b is a floating-point value with a nonzero fractional part. The built-in pow(a, b) function returns the same result as a**b . With three arguments, pow(a, b, c) returns the same result as (a**b)%c  but faster.

Comparisons

All objects, including numbers, can be compared for equality (==) and inequality (!=). Comparisons requiring order (<, <=, >, >=) may be used between any two numbers, unless either operand is complex, in which case they raise runtime exceptions. All these operators return Boolean values (True or False).

Bitwise Operations on Integers

Integers and long integers can be taken as strings of bits and used with the bitwise operations shown in Table 4-2. Bitwise operators have lower priority than arithmetic operators. Positive integers are conceptually extended by an infinite string of 0 bits on the left. Negative integers are represented in two’s complement notation, and therefore are conceptually extended by an infinite string of 1 bits on the left.

{mospagebreak title=Sequence Operations}

Python supports a variety of operations applicable to all sequences, including strings, lists, and tuples. Some sequence operations apply to all containers (including, for example, sets and dictionaries, which are not sequences), and some apply to all iterables (meaning "any object on which you can loop," as covered in "Iterables" on page 40; all containers, be they sequences or otherwise, are iterable, and so are many objects that are not containers, such as files, covered in "File Objects" on page 216, and generators, covered in "Generators" on page 78). In the following, I use the terms sequence, container, and iterable, quite precisely and specifically, to indicate exactly which operations apply to each category.

Sequences in General

Sequences are containers with items that are accessible by indexing or slicing. The built-in len function takes any container as an argument and returns the number of items in the container. The built-in min and max functions take one argument, a nonempty iterable whose items are comparable, and return the smallest and largest items, respectively. You can also call min and max with multiple arguments, in which case they return the smallest and largest arguments, respectively. The built-in sum function takes one argument, an iterable whose items are numbers, and returns the sum of the numbers.

Sequence conversions

There is no implicit conversion between different sequence types, except that plain strings are converted to Unicode strings if needed. (String conversion is covered in detail in "Unicode" on page 198.) You can call the built-ins tuple and list with a single argument (any iterable) to get a new instance of the type you’re calling, with the same items (in the same order) as in the argument.

Concatenation and repetition

You can concatenate sequences of the same type with the + operator. You can multiply a sequence S  by an integer n  with the * operator. S*n  or n*S  is the concatenation of n copies of S . When n<=0, S*n  is an empty sequence of the same type as S .

Membership testing

The x  in S operator tests to check whether object x equals any item in the sequence (or other kind of container or iterable) S . It returns True if it does and False if it doesn’t. The x not in S  operator is just like not (x in S). In the specific case of strings, though, x  in S  is more widely applicable; in this case, the operator tests whether x  equals any substring of string S , not just any single character.

Indexing a sequence

The nth item of a sequence S is denoted by an indexing: S[n]. Indexing is zero-based (S’ s first item is S[0]). If S  has L  items, the index n  may be 0, 1…up to and including L-1, but no larger. n  may also be -1, -2…down to and including L , but no smaller. A negative n  indicates the same item in S as L+n  does. In other words, S[-1], like S[L-1], is the last element of S , S[-2] is the next-to-last one, and so on. For example:

x = [1, 2, 3, 4]
x[1]                 # 2
x[-1]                # 4

Using an index >=L or <-L  raises an exception. Assigning to an item with an invalid index also raises an exception. You can add one or more elements to a list, but to do so you assign to a slice, not an item, as I’ll discuss shortly.

Please check back next week for the continuation of the article.