?? appendix_a.txt
字號:
>>> if 2+2 <= 4:
... print "Happy math"
...
Happy math
>>> x = 3
>>> if x > 4: print "More than 4"
... elif x > 3: print "More than 3"
... elif x > 2: print "More than 2"
... else: print "2 or less"
...
More than 2
>>> if isinstance(2, int):
... print "2 is an int" # 2.2+ test
... else:
... print "2 is not an int"
Python has no "switch" statement to compare one value with
multiple candidate matches. Occasionally, the repetition of
an expression being compared on multiple 'elif' lines looks
awkward. A "trick" in such a case is to use a dict as a
pseudo-switch. The following are equivalent, for example:
>>> if var.upper() == 'ONE': val = 1
... elif var.upper() == 'TWO': val = 2
... elif var.upper() == 'THREE': val = 3
... elif var.upper() == 'FOUR': val = 4
... else: val = 0
...
>>> switch = {'ONE':1, 'TWO':2, 'THREE':3, 'FOUR':4}
>>> val = switch.get(var.upper(), 0)
TOPIC -- Boolean Shortcutting
--------------------------------------------------------------------
The Boolean operators 'or' and 'and' are "lazy." That is, an
expression containing 'or' or 'and' evaluates only as far as it
needs to determine the overall value. Specifically, if the
first disjoin of an 'or' is true, the value of that disjoin
becomes the value of the expression, without evaluating the
rest; if the first conjoin of an 'and' is false, its value
likewise becomes the value of the whole expression.
Shortcutting is formally sufficient for switching and is
sometimes more readable and concise than "if/elif/else" blocks.
For example:
>>> if this: # 'if' compound statement
... result = this
... elif that:
... result = that
... else:
... result = 0
...
>>> result = this or that or 0 # boolean shortcutting
Compound shortcutting is also possible, but not necessarily
easy to read; for example:
>>> (cond1 and func1()) or (cond2 and func2()) or func3()
TOPIC -- 'for'/'continue'/'break' Statements
--------------------------------------------------------------------
The 'for' statement loops over the elements of a sequence. In
Python 2.2+, looping utilizes an iterator object (which
may not have a predetermined length)--but standard sequences
like lists, tuples, and strings are automatically transformed to
iterators in 'for' statements. In earlier Python versions, a
few special functions like 'xreadlines()' and 'xrange()' also
act as iterators.
Each time a 'for' statement loops, a sequence/iterator element is
bound to the loop variable. The loop variable may be a tuple with
named items, thereby creating bindings for multiple names in
each loop. For example:
>>> for x,y,z in [(1,2,3),(4,5,6),(7,8,9)]: print x, y, z, '*',
...
1 2 3 * 4 5 6 * 7 8 9 *
A particularly common idiom for operating on each item in a
dictionary is:
>>> for key,val in dct.items():
... print key, val, '*',
...
1 2 * 3 4 * 5 6 *
When you wish to loop through a block a certain number of
times, a common idiom is to use the 'range()' or 'xrange()'
built-in functions to create ad hoc sequences of the needed
length. For example:
>>> for _ in range(10):
... print "X", # '_' is not used in body
...
X X X X X X X X X X
However, if you find yourself binding over a range just to repeat
a block, this often indicates that you have not properly
understood the loop. Usually repetition is a way of operating on
a collection of related -things- that could instead be explicitly
bound in the loop, not just a need to do exactly the same thing
multiple times.
If the 'continue' statement occurs in a 'for' loop, the next loop
iteration proceeds without executing later lines in the block. If
the 'break' statement occurs in a 'for' loop, control passes past
the loop without executing later lines (except the 'finally'
block if the 'break' occurs in a 'try').
TOPIC -- 'map()', 'filter()', 'reduce()', and List Comprehensions
--------------------------------------------------------------------
Much like the 'for' statement, the built-in functions `map()`,
`filter()`, and `reduce()` perform actions based on a sequence of
items. Unlike a 'for' loop, these functions explicitly return a
value resulting from this application to each item. Each of these
three functional-programming style functions accepts a function
object as a first argument and sequence(s) as subsequent
argument(s).
The `map()` function returns a list of items of the same length
as the input sequence, where each item in the result is a
"transformation" of one item in the input. Where you
explicitly want such transformed items, use of `map()` is often
both more concise and clearer than an equivalent 'for' loop;
for example:
>>> nums = (1,2,3,4)
>>> str_nums = []
>>> for n in nums:
... str_nums.append(str(n))
...
>>> str_nums
['1', '2', '3', '4']
>>> str_nums = map(str, nums)
>>> str_nums
['1', '2', '3', '4']
If the function argument of `map()` accepts (or can accept)
multiple arguments, multiple sequences can be given as later
arguments. If such multiple sequences are of different lengths,
the shorter ones are padded with 'None' values. The special value
'None' may be given as the function argument, producing a
sequence of tuples of elements from the argument sequences.
>>> nums = (1,2,3,4)
>>> def add(x, y):
... if x is None: x=0
... if y is None: y=0
... return x+y
...
>>> map(add, nums, [5,5,5])
[6, 7, 8, 4]
>>> map(None, (1,2,3,4), [5,5,5])
[(1, 5), (2, 5), (3, 5), (4, None)]
The `filter()` function returns a list of those items in the
input sequence that satisfy a condition given by the function
argument. The function argument must accept one parameter,
and its return value is interpreted as a Boolean (in the usual
manner). For example
>>> nums = (1,2,3,4)
>>> odds = filter(lambda n: n%2, nums)
>>> odds
(1, 3)
Both `map()` and `filter()` can use function arguments that
have side effects, thereby making it possible--but not usually
desirable--to replace every 'for' loop with a `map()` or
`filter()` function. For example:
>>> for x in seq:
... # bunch of actions
... pass
...
>>> def actions(x):
... # same bunch of actions
... return 0
...
>>> filter(actions, seq)
[]
Some epicycles are needed for the scoping of block variables and
for 'break' and 'continue' statements. But as a general picture,
it is worth being aware of the formal equivalence between these
very different-seeming techniques.
The `reduce()` function takes as a function argument a function
with two parameters. In addition to a sequence second argument,
`reduce()` optionally accepts a third argument as an initializer.
For each item in the input sequence, `reduce()` combines the
previous aggregate result with the item, until the sequence is
exhausted. While `reduce()`--like `map()` and `filter()`--has a
loop-like effect of operating on every item in a sequence, its
main purpose is to create some sort of aggregation, tally, or
selection across indefinitely many items. For example:
>>> from operator import add
>>> sum = lambda seq: reduce(add, seq)
>>> sum([4,5,23,12])
44
>>> def tastes_better(x, y):
... # some complex comparison of x, y
... # either return x, or return y
... # ...
...
>>> foods = [spam, eggs, bacon, toast]
>>> favorite = reduce(tastes_better, foods)
List comprehensions (listcomps) are a syntactic form that was
introduced with Python 2.0. It is easiest to think of list
comprehensions as a sort of cross between for loops and the
`map()` or `filter()` functions. That is, like the functions,
listcomps are expressions that produce lists of items, based on
"input" sequences. But listcomps also use the keywords 'for' and
'if' that are familiar from statements. Moreover, it is typically
much easier to read a compound list comprehension expression than
it is to read corresponding nested `map()` and `filter()`
functions.
For example, consider the following small problem: You have a
list of numbers and a string of characters; you would like to
construct a list of all pairs that consist of a number from the
list and a character from the string, but only if the ASCII
ordinal is larger than the number. In traditional imperative
style, you might write:
>>> bigord_pairs = []
>>> for n in (95,100,105):
... for c in 'aei':
... if ord(c) > n:
... bigord_pairs.append((n,c))
...
>>> bigord_pairs
[(95, 'a'), (95, 'e'), (95, 'i'), (100, 'e'), (100, 'i')]
In a functional programming style you might write the nearly
unreadable:
>>> dupelms=lambda lst,n: reduce(lambda s,t:s+t,
... map(lambda l,n=n: [l]*n, lst))
>>> combine=lambda xs,ys: map(None,xs*len(ys), dupelms(ys,len(xs)))
>>> bigord_pairs=lambda ns,cs: filter(lambda (n,c):ord(c)>n,
... combine(ns,cs))
>>> bigord_pairs((95,100,105),'aei')
[(95, 'a'), (95, 'e'), (100, 'e'), (95, 'i'), (100, 'i')]
In defense of this FP approach, it has not -only- accomplished
the task at hand, but also provided the general combinatorial
function 'combine()' along the way. But the code is still
rather obfuscated.
List comprehensions let you write something that is both
concise and clear:
>>> [(n,c) for n in (95,100,105) for c in 'aei' if ord(c)>n]
[(95, 'a'), (95, 'e'), (95, 'i'), (100, 'e'), (100, 'i')]
As long as you have listcomps available, you hardly -need- a
general 'combine()' function, since it just amounts to
repeating the 'for' clause in a listcomp.
Slightly more formally, a list comprehension consists of the
following: (1) Surrounding square brackets (like a list
constructor, which it is). (2) An expression that usually, but
not by requirement, contains some names that get bound in the
'for' clauses. (3) One or more 'for' clauses that bind a name
repeatedly (just like a 'for' loop). (4) Zero or more 'if'
clauses that limit the results. Generally, but not by
requirement, the 'if' clauses contain some names that were
bound by the 'for' clauses.
List comprehensions may nest inside each other freely. Sometimes
a 'for' clause in a listcomp loops over a list that is defined by
another listcomp; once in a while a nested listcomp is even used
inside a listcomp's expression or 'if' clauses. However, it is
almost as easy to produce difficult-to-read code by excessively
nesting listcomps as it is by nesting `map()` and `filter()`
functions. Use caution and common sense about such nesting.
It is worth noting that list comprehensions are not as
referentially transparent as functional programming style
calls. Specifically, any names bound in 'for' clauses
remain bound in the enclosing scope (or global if the name is
so declared). These side effects put a minor extra burden on
you to choose distinctive or throwaway names for use in
listcomps.
TOPIC -- 'while'/'else'/'continue'/'break' Statements
--------------------------------------------------------------------
The 'while' statement loops over a block as long as the
expression after the 'while' remains true. If an 'else' block is
used within a compound 'while' statement, as soon as the
expression becomes false, the 'else' block is executed. The
'else' block is chosen even if the 'while' expression is
initially false.
If the 'continue' statement occurs in a 'while' loop, the next
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -