Python 笔记

Numbers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
>>> 8 / 5    # division always returns a floating point number
1.6


>>> 17 / 3 # classic division returns a float
5.666666666666667
>>>
>>> 17 // 3 # floor division discards the fractional part
5


>>> 2 ** 7 # 2 to the power of 7
128


>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06


>>> from fractions import Fraction
>>> Fraction(16, -10)
Fraction(-8, 5)
>>> Fraction(123)
Fraction(123, 1)
>>> Fraction()
Fraction(0, 1)
>>> Fraction('3/7')
Fraction(3, 7)
>>> Fraction(' -3/7 ')
Fraction(-3, 7)
>>> Fraction('1.414213 \t\n')
Fraction(1414213, 1000000)
>>> Fraction('-.125')
Fraction(-1, 8)
>>> Fraction('7e-6')
Fraction(7, 1000000)
>>> Fraction(2.25)
Fraction(9, 4)
>>> Fraction(1.1)
Fraction(2476979795053773, 2251799813685248)
>>> from decimal import Decimal
>>> Fraction(Decimal('1.1'))
Fraction(11, 10)

Strings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
>>> 'spam eggs'  # single quotes
'spam eggs'
>>> 'doesn\'t' # use \' to escape the single quote...
"doesn't"
>>> "doesn't" # ...or use double quotes instead
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'


>>> print('C:\some\name') # here \n means newline!
C:\some
ame
>>> print(r'C:\some\name') # note the r before the quote
C:\some\name


# String literals can span multiple lines. One way is using triple-quotes: """...""" or
# '''...'''. End of lines are automatically included in the string, but it’s possible
# to prevent this by adding a \ at the end of the line.
>>> print("""/
... Usage: thingy [OPTIONS]
... -h Display this usage message
... -H hostname Hostname to connect to
... """)
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
#here is a end of line


>>> # 3 times 'un', followed by 'ium'
>>> 3 * 'un' + 'ium'
'unununium'



# Two or more string literals (i.e. the ones enclosed between quotes)
# next to each other are automatically concatenated.
>>> 'Py' 'thon'
'Python'


>>> word = 'Python'
>>> word[0] # character in position 0
'P'
>>> word[5] # character in position 5
'n'
>>> word[-1] # last character
'n'
>>> word[-2] # second-last character
'o'
>>> word[-6]
'P'
>>> word[0:2] # characters from position 0 (included) to 2 (excluded)
'Py'
>>> word[2:5] # characters from position 2 (included) to 5 (excluded)
'tho'

# Note how the start is always included, and the end always excluded.
# This makes sure that s[:i] + s[i:] is always equal to s:
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'


>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34

List

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> squares[0] = 2
>>> squares
[2, 4, 9, 16, 25]
>>> squares.append(50)
>>> squares
[2, 4, 9, 16, 25, 50]

>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'


>>> # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1
>>> while b < 10:
... print(b)
... a, b = b, a+b
...
1
1
2
3
5
8

More Control Flow Tools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# if Statements
>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
... x = 0
... print('Negative changed to zero')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print('Single')
... else:
... print('More')
...
More


# for Statements
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12


# The range() Function
>>> for i in range(5):
... print(i)
...
0
1
2
3
4

range(5, 10)
5 through 9

range(0, 10, 3)
0, 3, 6, 9

range(-10, -100, -30)
-10, -40, -70

>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb


# Loop statements may have an else clause; it is executed when the loop terminates
# through exhaustion of the list (with for) or when the condition becomes false
# (with while), but not when the loop is terminated by a break statement.

>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print(n, 'equals', x, '*', n//x)
... break
... else:
... # loop fell through without finding a factor
... print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3


# pass Statements
# The pass statement does nothing. It can be used when a statement is
# required syntactically but the program requires no action.

>>> while True:
... pass # Busy-wait for keyboard interrupt (Ctrl+C)
...


# Defining Functions
>>> def fib(n): # write Fibonacci series up to n
... """Print a Fibonacci series up to n."""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597


# More on Defining Functions
## Default Argument Values
>>> def ask_ok(prompt, retries=4, reminder='Please try again!'):
... while True:
... ok = input(prompt)
... if ok in ('y', 'ye', 'yes'):
... return True
... if ok in ('n', 'no', 'nop', 'nope'):
... return False
... retries = retries - 1
... if retries < 0:
... raise ValueError('invalid user response')
... print(reminder)

# This function can be called in several ways:
# ask_ok('Do you really want to quit?')
# ask_ok('OK to overwrite the file?', 2)
# ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')


## Keyword Arguments
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")

# accepts one required argument (voltage) and three optional arguments (state, action, and type).
# This function can be called in any of the following ways:
parrot(1000) # 1 positional argument
parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword

# but all the following calls would be invalid:
parrot() # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument

# When a final formal parameter of the form **name is present, it receives a dictionary
# (see Mapping Types — dict) containing all keyword arguments except for those corresponding
# to a formal parameter. This may be combined with a formal parameter of the form *name
# (described in the next subsection) which receives a tuple containing the positional
# arguments beyond the formal parameter list. (*name must occur before **name.)
def cheeseshop(kind, *arguments, **keywords):
print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
keys = sorted(keywords.keys())
for kw in keys:
print(kw, ":", keywords[kw])

# It could be called like this:
cheeseshop("Limburger", "It's very runny, sir.",
"It's really very, VERY runny, sir.",
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch")



## Lambda Expressions(the left of colon is params, right as the return value)

>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43


## Documentation Strings

>>> def my_function():
... """Do nothing, but document it.
... No, really, it doesn't do anything.
... """
... pass

>>> print(my_function.__doc__)
Do nothing, but document it.
No, really, it doesn't do anything.

Data Structures

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# More on Lists

>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4) # Find next banana starting a position 4
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'


## Using Lists as Stacks

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]


## Using Lists as Queues

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])


## List Comprehensions

# List comprehensions provide a concise way to create lists.
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# We can calculate the list of squares without any side effects using:
squares = list(map(lambda x: x**2, range(10)))
# or, equivalently:
squares = [x**2 for x in range(10)]

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

## Nested List Comprehensions

>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
...
>>> # The following list comprehension will transpose rows and columns:
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

# In the real world, you should prefer built-in functions to complex flow statements.
# The zip() function would do a great job for this use case:
>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]


## The del statement

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]
del can also be used to delete entire variables:

>>>
>>> del a


## Tuples and Sequences

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

>>> t = 12345, 54321, 'hello!'
>>> x, y, z = t
>>> x
12345
>>> y
54321
>>> z
'hello!'


## Sets

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # show that duplicates have been removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # fast membership testing
True
>>> 'crabgrass' in basket
False

>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b # letters in either a or b
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # letters in both a and b
{'a', 'c'}
>>> a ^ b # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}
Similarly to list comprehensions, set comprehensions are also supported:

>>>
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}


## Dictionaries

>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

# The dict() constructor builds dictionaries directly from sequences of key-value pairs:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}

# In addition, dict comprehensions can be used to create dictionaries from
# arbitrary key and value expressions:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

# When the keys are simple strings, it is sometimes easier to specify pairs using keyword arguments:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}


## More on Conditions

# The Boolean operators and and or are so-called short-circuit operators: their arguments
# are evaluated from left to right, and evaluation stops as soon as the outcome is determined.
# For example, if A and C are true but B is false, A and B and C does not evaluate the expression C.
# When used as a general value and not as a Boolean, the return value of a short-circuit operator
# is the last evaluated argument.

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> string1 and string2
''
>>> string1 and string2 and string3
''
>>> string2 and string3
'Hammer Dance'
>>> string1 or string2
'Trondheim'
>>> string1 or string2 or string3
'Trondheim'


## Comparing Sequences and Other Types

(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)

Modules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# create a file called fibo.py in the current directory with the following contents:

# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()

def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result

>>> import fibo
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
>>> fib = fibo.fib2
>>> fib(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377


## Executing modules as scripts
#run a Python module with
python fibo.py <arguments>


## “Compiled” Python files
# To speed up loading modules, Python caches the compiled version of each module in the __pycache__
# directory under the name module.version.pyc, where the version encodes the format of the compiled file;
# it generally contains the Python version number. For example, in CPython release 3.3 the compiled
# version of spam.py would be cached as __pycache__/spam.cpython-33.pyc. This naming convention allows
# compiled modules from different releases and different versions of Python to coexist.

# You can use the -O or -OO switches on the Python command to reduce the size of a compiled module.
# The -O switch removes assert statements, the -OO switch removes both assert statements and
# __doc__ strings.

# A program doesn’t run any faster when it is read from a .pyc file than when it is read from a .py file;
# the only thing that’s faster about .pyc files is the speed with which they are loaded.



# The dir() Function

# The built-in function dir() is used to find out which names a module defines.
# It returns a sorted list of strings:
>>> import fibo, sys
>>> dir(fibo)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__',
'__spec__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__',
'__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache',
'_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags',
'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook',
'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_asyncgen_hooks',
'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding','getdlopenflags',
'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount',
'getsizeof', 'getswitchinterval', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'set_asyncgen_hooks','set_coroutine_wrapper',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval','settrace',
'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions']


## Packages

sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...


# The __init__.py files are required to make Python treat the directories as containing packages; this is
# done to prevent directories with a common name, such as string, from unintentionally hiding valid
# modules that occur later on the module search path. In the simplest case, __init__.py can just be an
# empty file, but it can also execute initialization code for the package or set the __all__ variable,
# described later.

Input and Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# Fancier Output Formatting

# str() and repr()
>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1/7)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print(s)
The value of x is 32.5, and y is 40000...
>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print(hellos)
'hello, world\n'
>>> # The argument to repr() may be any Python object:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"

# Basic usage of str.rjust()、str.ljust()、str.center()、str.zfill()
>>> for x in range(1, 11):
... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
... # Note use of 'end' on previous line
... print(repr(x*x*x).rjust(4))
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000

>>> for x in range(1, 11):
... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
...
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000

>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'

# Basic usage of the str.format()
>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"

>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam

>>> print('This {food} is {adjective}.'.format(
... food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.

>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred', other='Georg'))
The story of Bill, Manfred, and Georg.

# '!a' (apply ascii()), '!s' (apply str()) and '!r' (apply repr()) can be used to convert the value
# before it is formatted:
>>> contents = 'eels'
>>> print('My hovercraft is full of {}.'.format(contents))
My hovercraft is full of eels.
>>> print('My hovercraft is full of {!r}.'.format(contents))
My hovercraft is full of 'eels'.

>>> contents = '\u9600'
>>> print('My hovercraft is full of {!a}.'.format(contents))
My hovercraft is full of '\u9600'.
>>> print('My hovercraft is full of {!s}.'.format(contents))
My hovercraft is full of 阀.

>>> import math
>>> print('The value of PI is approximately {0:.3f}.'.format(math.pi))
The value of PI is approximately 3.142.

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
... print('{0:10} ==> {1:10d}'.format(name, phone))
...
Jack ==> 4098
Dcab ==> 7678
Sjoerd ==> 4127

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
... 'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

# This could also be done by passing the table as keyword arguments with the ‘**’ notation
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678



# Reading and Writing Files

# open() returns a file object, and is most commonly used with two arguments: open(filename, mode).
# 'r' - only be read;
# 'w' - only writing;
# 'a' - open the file for appending;
# 'r+' - opens the file for both reading and writing

# 'b' - appended to the mode opens the file in binary mode
>>> f = open('testInputOutput.txt', 'r')
>>> f.read()
'This is the first line of the file.\nSecond line of the file.'
>>> f.readline()
''
>>> f.read()
''
>>> f = open('testInputOutput.txt', 'r')
>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file.'
>>> f.readline()
''

>>> for line in f:
... print(line, end='')
...
This is the first line of the file.
Second line of the file.

# f.tell() returns an integer giving the file object’s current position in the file
>>> f = open('testInputOutput.txt', 'r')
>>> f.tell()
0
>>> f.readline()
'This is the first line of the file.\n'
>>> f.tell()
36

# To change the file object’s position, use f.seek(offset, from_what). The position is computed from
# adding offset to a reference point; the reference point is selected by the from_what argument.
# A from_what value of 0 measures from the beginning of the file, 1 uses the current file position,
# and 2 uses the end of the file as the reference point. from_what can be omitted and defaults to 0,
# using the beginning of the file as the reference point.
>>> f = open('workfile', 'rb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5) # Go to the 6th byte in the file
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
13
>>> f.read(1)
b'd'

# When you’re done with a file, call f.close() to close it and free up any
# system resources taken up by the open file

# It is good practice to use the with keyword when dealing with file objects.
# This has the advantage that the file is properly closed after its suite finishes,
# even if an exception is raised on the way. It is also much shorter than writing
# equivalent try-finally blocks:
>>> with open('workfile', 'r') as f:
... read_data = f.read()
>>> f.closed
True


# Saving structured data with json

# If you have an object x, you can view its JSON string representation with a simple line of code:
>>> json.dumps([1, 'simple', 'list'])
'[1, "simple", "list"]'

# Another variant of the dumps() function, called dump(), simply serializes the object to a text file.
# So if f is a text file object opened for writing, we can do this:
json.dump(x, f)

# To decode the object again, if f is a text file object which has been opened for reading:
x = json.load(f)

Errors and Exceptions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Syntax Errors

# the error is detected at the function print(), since a colon (':') is missing before it
>>> while True print('Hello world')
File "<stdin>", line 1
while True print('Hello world')
^
SyntaxError: invalid syntax



# Exceptions

# Errors detected during execution are called exceptions
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly



# Handling Exceptions

# Look at the following example, which asks the user for input until a valid integer has been entered,
# but allows the user to interrupt the program (using Control-C or whatever the operating system
# supports); note that a user-generated interruption is signalled by raising the
# KeyboardInterrupt exception.
while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again...")

# A try statement may have more than one except clause, to specify handlers for different exceptions.
# At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding
# try clause, not in other handlers of the same try statement. An except clause may name multiple
# exceptionsas a parenthesized tuple, for example:
... except (RuntimeError, TypeError, NameError):
... pass

# A class in an except clause is compatible with an exception if it is the same class or a base class
# thereof (but not the other way around — an except clause listing a derived class is not compatible
# with a base class). For example, the following code will print B, C, D in that order:
# if the except clauses were reversed (with except B first), it would have printed B, B, B
# — the first matching except clause is triggered.
>>> class B(Exception):
... pass
...
>>> class C(B):
... pass
...
>>> class D(C):
... pass
...
>>> for cls in [B, C, D]:
... try:
... raise cls() # raise: throw an exception of user-defined
... except D:
... print("D")
... except C:
... print("C")
... except B:
... print("B")
...
B
C
D

>>> for cls in [B, C, D]:
... try:
... raise cls()
... except B:
... print("B")
... except C:
... print("C")
... except D:
... print("D")
...
B
B
B

# The try ... except statement has an optional else clause, which, when present, must follow
# all except clauses. It is useful for code that must be executed if the try clause does not
# raise an exception. For example:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()



# Raising Exceptions

The raise statement allows the programmer to force a specified exception to occur. For example:
>>> raise NameError('HiThere')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere



# User-defined Exceptions

class Error(Exception):
"""Base class for exceptions in this module."""
pass

class InputError(Error):
"""Exception raised for errors in the input.

Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""

def __init__(self, expression, message):
self.expression = expression
self.message = message

class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.

Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""

def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message



# Defining Clean-up Actions
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 2, in <module>



# Predefined Clean-up Actions
# The with statement allows objects like files to be used in a way that ensures they are always
# cleaned up promptly and correctly.
with open("myfile.txt") as f:
for line in f:
print(line, end="")

Classes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# Python classes provide all the standard features of Object Oriented Programming: the class inheritance
# mechanism allows multiple base classes, a derived class can override any methods of its base class or
# classes, and a method can call the method of a base class with the same name. Objects can contain
# arbitrary amounts and kinds of data. As is true for modules, classes partake of the dynamic nature of
# Python: they are created at runtime, and can be modified further after creation.


# Scopes and Namespaces Example

# This is an example demonstrating how to reference the different scopes and namespaces, and how
# global and nonlocal affect variable binding:
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

# Note how the local assignment (which is default) didn’t change scope_test‘s binding of spam. The
# nonlocal assignment changed scope_test‘s binding of spam, and the global assignment changed the
# module-level binding.

# Names listed in a global statement must not be used in the same code block textually preceding
# that global statement.



# Class Objects

class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'

# MyClass.i and MyClass.f are valid attribute references, returning an integer and a function object
# creates a new instance of the class and assigns this object to the local variable x

x = MyClass()

# Therefore a class may define a special method named __init__()

>>> class Complex:
... def __init__(self, realpart, imagpart):
... self.r = realpart
... self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)

# Instance Objects
x.counter = 1
while x.counter < 10:
x.counter = x.counter * 2
print(x.counter)
del x.counter

# Method Objects

# Usually, a method is called right after it is bound:
x.f()

# In the MyClass example, this will return the string 'hello world'. However, it is not necessary to
# call a method right away: x.f is a method object, and can be stored away and called at a later time.
xf = x.f
while True:
print(xf())


# Class and Instance Variables

# Generally speaking, instance variables are for data unique to each instance and class variables
# are for attributes and methods shared by all instances of the class:
class Dog:
tricks = [] # mistaken use of a class variable
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks # unexpectedly shared by all dogs
['roll over', 'play dead']

# Methods may call other methods by using method attributes of the self argument:
class Bag:
def __init__(self):
self.data = []

def add(self, x):
self.data.append(x)

def addtwice(self, x):
self.add(x)
self.add(x)



# Inheritance

class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>



# Multiple Inheritance

class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>



# Private Variables

class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)

def update(self, iterable):
for item in iterable:
self.items_list.append(item)

__update = update # private copy of original update() method

class MappingSubclass(Mapping):

def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)



# Odds and Ends

# Sometimes it is useful to have a data type similar to the Pascal “record” or C “struct”,
# bundling together a few named data items. An empty class definition will do nicely:

class Employee:
pass

john = Employee() # Create an empty employee record

# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000



# Iterators

# By now you have probably noticed that most container objects can be looped over using a for statement:
for element in [1, 2, 3]:
print(element)
for element in (1, 2, 3):
print(element)
for key in {'one':1, 'two':2}:
print(key)
for char in "123":
print(char)
for line in open("myfile.txt"):
print(line, end='')

# Behind the scenes, the for statement calls iter() on the container object. The function returns an
# iterator object that defines the method __next__() which accesses elements in the container one at
# a time. When there are no more elements, __next__() raises a StopIteration exception which tells
# the for loop to terminate. You can call the __next__() method using the next() built-in function;
# this example shows how it all works:

>>> s = 'abc'
>>> it = iter(s)
>>> it
<str_iterator object at 0x100791208>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration



# Generators
# Generators are a simple and powerful tool for creating iterators. They are written like regular
# functions but use the yield statement whenever they want to return data.
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]

>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g



# Generator Expressions

# Some simple generators can be coded succinctly as expressions using a syntax similar to list
# comprehensions but with parentheses instead of brackets.
>>> sum(i*i for i in range(10)) # sum of squares
285

>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260

>>> from math import pi, sin
>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}

>>> unique_words = set(word for line in page for word in line.split())

>>> valedictorian = max((student.gpa, student.name) for student in graduates)

>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']

Brief Tour of the Standard Library

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# Operating System Interface

>>> import os
>>> os.getcwd() # Return the current working directory
'/Users/dll/Desktop'
>>> os.chdir('/Users/dll/PycharmProjects/TestByTerminal') # Change current working directory
>>> os.getcwd()
'/Users/dll/PycharmProjects/TestByTerminal'
>>> os.system('mkdir today') # Run the command mkdir in the system shell
0
>>> os.chdir('/Users/dll/PycharmProjects/TestByTerminal/today')
>>> os.getcwd()
'/Users/dll/PycharmProjects/TestByTerminal/today'

# Be sure to use the import os style instead of from os import *. This will keep os.open() from
# shadowing the built-in open() function which operates much differently.

# The built-in dir() and help() functions are useful as interactive aids for working with large
# modules like os:
>>> import os
>>> dir(os)
<returns a list of all module functions>
>>> help(os)
<returns an extensive manual page created from the module's docstrings>

#For daily file and directory management tasks, the shutil module provides a higher level interface
#that is easier to use:
>>> import shutil
>>> shutil.copyfile('data.db', 'archive.db')
'archive.db'
>>> shutil.move('/build/executables', 'installdir')
'installdir'



# File Wildcards
# The glob module provides a function for making file lists from directory wildcard searches:
>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']



# Command Line Arguments
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']



# Error Output Redirection and Program Termination
# The sys module also has attributes for stdin, stdout, and stderr. The latter is useful for emitting
# warnings and error messages to make them visible even when stdout has been redirected:

>>> sys.stderr.write('Warning, log file not found starting a new one\n')
Warning, log file not found starting a new one

# The most direct way to terminate a script is to use sys.exit().



# String Pattern Matching
# The re module provides regular expression tools for advanced string processing. For complex matching
# and manipulation, regular expressions offer succinct, optimized solutions:
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'

# \number
# Matches the contents of the group of the same number. Groups are numbered starting from 1.
# For example, (.+) \1 matches 'the the' or '55 55', but not 'thethe' (note the space after the
# group). This special sequence can only be used to match one of the first 99 groups. If the first
# digit of number is 0, or number is 3 octal digits long, it will not be interpreted as a group match,
# but as the character with octal value number. Inside the '[' and ']' of a character class, all
# numeric escapes are treated as characters.

# When only simple capabilities are needed, string methods are preferred because they are easier to
# read and debug:
>>> 'tea for too'.replace('too', 'two')
'tea for two'



# Mathematics
# The math module gives access to the underlying C library functions for floating point math:
>>> import math
>>> math.cos(math.pi / 4)
0.70710678118654757
>>> math.log(1024, 2)
10.0

# The random module provides tools for making random selections:
>>> import random
>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10) # sampling without replacement
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random() # random float
0.17970987693706186
>>> random.randrange(6) # random integer chosen from range(6)
4

# The statistics module calculates basic statistical properties (the mean, median, variance, etc.)
# of numeric data:
>>> import statistics
>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
>>> statistics.mean(data)
1.6071428571428572
>>> statistics.median(data)
1.25
>>> statistics.variance(data)
1.3720238095238095



# Dates and Times
>>> # dates are easily constructed and formatted
>>> from datetime import date
>>> now = date.today()
>>> now
datetime.date(2003, 12, 2)
>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
'12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'

>>> # dates support calendar arithmetic
>>> birthday = date(1964, 7, 31)
>>> age = now - birthday
>>> age.days
14368



# Data Compression
# Common data archiving and compression formats are directly supported by modules including: zlib,
# gzip, bz2, lzma, zipfile and tarfile.

>>> import zlib
>>> s = b'witch which has which witches wrist watch'
>>> len(s)
41
>>> t = zlib.compress(s)
>>> len(t)
37
>>> zlib.decompress(t)
b'witch which has which witches wrist watch'
>>> zlib.crc32(s)
226805979



# Performance Measurement

# Some Python users develop a deep interest in knowing the relative performance of different approaches
# to the same problem. Python provides a measurement tool that answers those questions immediately.

# For example, it may be tempting to use the tuple packing and unpacking feature instead of the
# traditional approach to swapping arguments. The timeit module quickly demonstrates a modest
# performance advantage:
>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791

# In contrast to timeit‘s fine level of granularity, the profile and pstats modules provide tools
# for identifying time critical sections in larger blocks of code.



# Quality Control
# One approach for developing high quality software is to write tests for each function as it is
# developed and to run those tests frequently during the development process.

# The doctest module provides a tool for scanning a module and validating tests embedded in a
# program’s docstrings. Test construction is as simple as cutting-and-pasting a typical call
# along with its results into the docstring. This improves the documentation by providing the
# user with an example and it allows the doctest module to make sure the code remains true to
# the documentation:

def average(values):
"""Computes the arithmetic mean of a list of numbers.

>>> print(average([20, 30, 70]))
40.0
"""
return sum(values) / len(values)

import doctest
doctest.testmod() # automatically validate the embedded tests

# The unittest module is not as effortless as the doctest module, but it allows a more comprehensive
# set of tests to be maintained in a separate file:

import unittest

class TestStatisticalFunctions(unittest.TestCase):
def test_average(self):
self.assertEqual(average([20, 30, 70]), 50.0)
self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
with self.assertRaises(ZeroDivisionError):
average([])
with self.assertRaises(TypeError):
average(20, 30, 70)

unittest.main() # Calling from the command line invokes all tests

Brief Tour of the Standard Library — Part II

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
#Output Formatting

# The reprlib module provides a version of repr() customized for abbreviated displays of large or
# deeply nested containers, default deep is six:
>>> import reprlib
>>> reprlib.repr(set('supercalifragilisticexpialidocious'))
"{'a', 'c', 'd', 'e', 'f', 'g', ...}"

# The pprint module offers more sophisticated control over printing both built-in and user defined
# objects in a way that is readable by the interpreter. When the result is longer than one line,
# the “pretty printer” adds line breaks and indentation to more clearly reveal data structure:
>>> import pprint
>>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]]
>>> pprint.pprint(t, width = 30)
[[[['black', 'cyan'],
'white',
['green', 'red']],
[['magenta', 'yellow'],
'blue']]]
>>> pprint.pprint(t, width = 60)
[[[['black', 'cyan'], 'white', ['green', 'red']],
[['magenta', 'yellow'], 'blue']]]

# The textwrap module formats paragraphs of text to fit a given screen width
>>> import textwrap
>>> doc = """The wrap() method is just like fill() except that it returns
... a list of strings instead of one big string with newlines to separate
... the wrapped lines."""
...
>>> print(textwrap.fill(doc, width=40))
The wrap() method is just like fill()
except that it returns a list of strings
instead of one big string with newlines
to separate the wrapped lines.

# The locale module accesses a database of culture specific data formats. The grouping attribute
# of locale’s format function provides a direct way of formatting numbers with group separators:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'English_United States.1252')
'English_United States.1252'
>>> conv = locale.localeconv() # get a mapping of conventions
>>> x = 1234567.8
>>> locale.format("%d", x, grouping=True)
'1,234,567'
>>> locale.format_string("%s%.*f", (conv['currency_symbol'],
... conv['frac_digits'], x), grouping=True)
'$1,234,567.80'



# Templating

# The string module includes a versatile Template class with a simplified syntax suitable for
# editing by end-users. This allows users to customize their applications without having to alter
# the application.

# The format uses placeholder names formed by $ with valid Python identifiers (alphanumeric
# characters and underscores). Surrounding the placeholder with braces allows it to be followed by
# more alphanumeric letters with no intervening spaces. Writing $$ creates a single escaped $:
>>> from string import Template
>>> t = Template('${village}folk send $$10 to $cause.')
>>> t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'

>>> import time, os.path
>>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
>>> class BatchRename(Template):
... delimiter = '%'
>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ')
Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f

>>> t = BatchRename(fmt)
>>> date = time.strftime('%d%b%y')
>>> for i, filename in enumerate(photofiles):
... base, ext = os.path.splitext(filename)
... newname = t.substitute(d=date, n=i, f=ext)
... print('{0} --> {1}'.format(filename, newname))

img_1074.jpg --> Ashley_0.jpg
img_1076.jpg --> Ashley_1.jpg
img_1077.jpg --> Ashley_2.jpg



# Working with Binary Data Record Layouts

# The struct module provides pack() and unpack() functions for working with variable length binary
# record formats. The following example shows how to loop through header information in a ZIP file
# without using the zipfile module. Pack codes "H" and "I" represent two and four byte unsigned
# numbers respectively. The "<" indicates that they are standard size and in little-endian byte
# order:
import struct

with open('myfile.zip', 'rb') as f:
data = f.read()

start = 0
for i in range(3): # show the first 3 file headers
start += 14
fields = struct.unpack('<IIIHH', data[start:start+16])
crc32, comp_size, uncomp_size, filenamesize, extra_size = fields
start += 16
filename = data[start:start+filenamesize]
start += filenamesize
extra = data[start:start+extra_size]
print(filename, hex(crc32), comp_size, uncomp_size)

start += extra_size + comp_size # skip to the next header



# Multi-threading

import threading, zipfile

class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile

def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
print('Finished background zip of:', self.infile)

background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
print('The main program continues to run in foreground.')

background.join() # Wait for the background task to finish
print('Main program waited until background was done.')



# Logging

>>> import logging
>>> logging.debug('Debugging information')
>>> logging.info('Informational message')
>>> logging.warning('Warning:config file %s not found', 'server.conf')
WARNING:root:Warning:config file server.conf not found
>>> logging.error('Error occurred')
ERROR:root:Error occurred
>>> logging.critical('Critical error -- shutting down')
CRITICAL:root:Critical error -- shutting down

# By default, informational and debugging messages are suppressed and the output is sent to
# standard error. Other output options include routing messages through email, datagrams,
# sockets, or to an HTTP Server. New filters can select different routing based on message
# priority: DEBUG, INFO, WARNING, ERROR, and CRITICAL.



# Weak References

# This approach works fine for most applications but occasionally there is a need to track objects
# only as long as they are being used by something else. Unfortunately, just tracking them creates
# a reference that makes them permanent. The weakref module provides tools for tracking objects
# without creating a reference. When the object is no longer needed, it is automatically removed
# from a weakref table and a callback is triggered for weakref objects. Typical applications
# include caching objects that are expensive to create:
>>> import weakref, gc
>>> class A:
... def __init__(self, value):
... self.value = value
... def __repr__(self):
... return str(self.value)
...
>>> a = A(10)
>>> d = weakref.WeakValueDictionary()
>>> d['primary'] = a
>>> d['primary']
10
>>> gc.collect()
22
>>> d['primary']
10
>>> del a
>>> gc.collect()
0
>>> d['primary']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/weakref.py", line 131, in __getitem__
o = self.data[key]()
KeyError: 'primary'



# Tools for Working with Lists

# Many data structure needs can be met with the built-in list type. However, sometimes there is a
# need for alternative implementations with different performance trade-offs.

# The array module provides an array() object that is like a list that stores only homogeneous
# data and stores it more compactly. The following example shows an array of numbers stored as
# two byte unsigned binary numbers (typecode "H") rather than the usual 16 bytes per entry for
# regular lists of Python int objects:
>>> from array import array
>>> a = array('H', [4000, 10, 700, 22222])
>>> sum(a)
26932
>>> a[1:3]
array('H', [10, 700])

# The collections module provides a deque() object that is like a list with faster appends and
# pops from the left side but slower lookups in the middle. These objects are well suited for
# implementing queues and breadth first tree searches:
>>> from collections import deque
>>> d = deque(["task1", "task2", "task3"])
>>> d.append("task4")
>>> print("Handling", d.popleft())
Handling task1

# In addition to alternative list implementations, the library also offers other tools such as
# the bisect module with functions for manipulating sorted lists:
>>> import bisect
>>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
>>> bisect.insort(scores, (300, 'ruby'))
>>> scores
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]

# The heapq module provides functions for implementing heaps based on regular lists. The lowest
# valued entry is always kept at position zero. This is useful for applications which repeatedly
# access the smallest element but do not want to run a full list sort:
>>> from heapq import heapify, heappop, heappush
>>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(data) # rearrange the list into heap order
>>> heappush(data, -5) # add a new entry
>>> [heappop(data) for i in range(3)] # fetch the three smallest entries
[-5, 0, 1]



# Decimal Floating Point Arithmetic

# The decimal module offers a Decimal datatype for decimal floating point arithmetic. Compared to
# the built-in float implementation of binary floating point, the class is especially helpful for
1. financial applications and other uses which require exact decimal representation,
2. control over precision,
3. control over rounding to meet legal or regulatory requirements,
4. tracking of significant decimal places, or
5. applications where the user expects the results to match calculations done by hand.

>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(.70 * 1.05, 2)
0.73


>>> Decimal('1.00') % Decimal('.10')
Decimal('0.00')
>>> 1.00 % 0.10
0.09999999999999995

>>> sum([Decimal('0.1')]*10) == Decimal('1.0')
True
>>> sum([0.1]*10) == 1.0
False


>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')

scope of variable

Python 中只有模块(module)、类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这这些语句内定义的变量,外部也可以访问,如下代码:

1
2
3
4
5
6
>>> if True:
... msg = 'I am from Runoob'
...
>>> msg
'I am from Runoob'
>>>