4.1. if
Statements
4.2. for
Statements
Python’s
for
statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence.
the behavior of modifying a collection while looping it can be tricky, so it is suggested that
Loop the copy of the collection
1
2
3
4# Strategy: Iterate over a copy
for user, status in users.copy().items():
if status == 'inactive':
del users[user]create a new collection with the original one.
1
2
3
4
5# Strategy: Create a new collection
active_users = {}
for user, status in users.items():
if status == 'active':
active_users[user] = status4.3. The
range()
Function
To iterate over the indices of a sequence, you can combine
range()
andlen()
as follows:1
2for i in range(len(collection)):
item = collection[i]When looping through a sequence, the position index and corresponding value can be retrieved at the same time using the enumerate() function.
1
2
3
4
5
6for i , v in enumerate(ls):
print(i,v)
0 tic
1 tac
2 toeSee more at Looping Techniques.
the return value of range() is an object which returns the successive items of the desired sequence when you iterate over it, but it doesn’t really make the list, thus saving space. So it is iterable
We say such an object is iterable, that is, suitable as a target for functions and constructs that expect something from which they can obtain successive items until the supply is exhausted.
4.4. break
and continue
Statements, and else
Clauses on Loops
The
for
statement can have anelse
clause, which will be executed if the loop do NOT terminated with abreak
statement1
2
3
4
5
6for i in range(2, 50):
for x in range(2,i):
if i % x == 0:
break
else:
print(i , "is a prime number")1
2
3
4
5
6
7
8
9
10
11
12
13
14
152 is a prime number
3 is a prime number
5 is a prime number
7 is a prime number
11 is a prime number
13 is a prime number
17 is a prime number
19 is a prime number
23 is a prime number
29 is a prime number
31 is a prime number
37 is a prime number
41 is a prime number
43 is a prime number
47 is a prime numbera
try
statement’selse
clause runs when no exception occurs, and a loop’selse
clause runs when nobreak
occurs. For more on thetry
statement and exceptions, see Handling Exceptions.
4.5. pass
Statements
The
pass
statement does nothing. It can be used when a statement is required syntactically but the program requires no action
it is commonly used for:
- creating minimal classes
- be used is as a place-holder for a function or conditional body when you are working on new code, allowing you to keep thinking at a more abstract level.
4.6. Defining Functions
The first statement of the function body can optionally be a string literal; this string literal is the function’s documentation string, or Documentation Strings. It’s good practice to include docstrings in code that you write, so make a habit of it.
1
2
3def DoNothing():
"""I am a lazy function"""
passThe execution of a function introduces a new symbol table used for the local variables of the function. The sequence of refering is
- local symbol table(created by the function)
- the local symbol tables of enclosing functions(can be referred by a nonlocal statement)
- the global symbol table(can be referred by a global statement)
- the table of built-in names
1
2
3
4
5
6
7
8
9
10
11
12
13
14
151] # create a variable in the global symbol table ls = [
def f():
2,3] # will create a name in the local symbol table created by the function when called ls = [
return
ls
[1]
f()
# f() does not change the value of ls ls
[1]
def ff():
# will use the name in the global variable table directly print(ls)
ff()
[1]
The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object).[1] When a function calls another function, a new local symbol table is created for that call.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def exchange(a,b):
... """Intended to exchange the value of parameters a and b\
but failed"""
a , b = b ,a
return a,b
3,4) exchange(
(4, 3)
999 x =
666 y =
exchange(x,y)
(666, 999)
x
999
y
666A function definition associates the function name with the function object in the current symbol table. The interpreter recognizes the object pointed to by that name as a user-defined function. Other names can also point to that same function object and can also be used to access the function: (works like C function pointer from my prespective)
1
2
3
4
5
6
7
8
9exchange
<function exchange at 0x109a5cc10>
newname = exchange
id(exchange)
4456827920
id(newname)
4456827920
newname(x,y)
(666, 999)every function has a return value, functions without a
return
statement have the return value ofNone
(the interpreter often suppress it, so you need printing it out to make it visible)(Falling off the end of a function also returnsNone
.)(None
can be similar tovoid
in C?)1
2
3
4
5
6def Nothing():
pass
Nothing()
print(Nothing())
None4.7. More on Defining Functions
There are three form of defining arguments, which can be combined.
4.7.1. Default Argument Values
non-default argument shouldn’t follow default argument
The default values are evaluated at the point of function definition in the defining scope, so that
1
2
3
4
5
6
75 i =
def f(arg = 5):
print(arg)
6 i =
f()
5The default value is evaluated only once. So when the argument is mutable, such as list or dictionary, it will be shared between function calls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def g(a , L = []): # shared version
L.append(a)
return L
print(g(1))
print(g(2))
print(g(3))
def f(a, L=None): # non-shared version
if L is None:
L = []
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))1
2
3
4
5
6[1]
[1, 2]
[1, 2, 3]
[1]
[2]
[3]4.7.2. Keyword Arguments
Functions can also be called using keyword arguments of the form
kwarg=value
each argument gets value only once, the order doesn’t matter.
1
2
3
4
5
6
7def f(a1 , a2 =2 , a3 =3 ):
print(a1, a2 ,a3)
4 , a1 = 0 ) f(a2 =
0 4 3
99 , a3 = 123) # In a function call, keyword arguments must follow positional arguments. f(
99 2 123arguments can be passed by using tuples and dictionaries
*name
which receives a tuple containing the positional arguments beyond the formal parameter list.**name
is present, it receives a dictionary containing all keyword arguments except for those corresponding to a formal parameter.Note that the order in which the keyword arguments are printed is guaranteed to match the order in which they were provided in the function call.
1
2
3
4
5
6def f(defaultarg , *arglist ):
print(defaultarg)
type(arglist)) print(arglist ,
0 , 1, 2 , 3 , 's') f(
0
(1, 2, 3, 's') <class 'tuple'>1
2
3
4
5
6
7
8
9def fun(**list):
list , type(list)) print(
0 , 1 , 2) fun(
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes 0 positional arguments but 3 were given
0 , b = 1 , c = 3) fun ( a =
{'a': 0, 'b': 1, 'c': 3} <class 'dict'>/
and*
can optionally be used as parameters type indicators1
2
3
4
5
6def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only4.7.3.1. Positional-or-Keyword Arguments
If /
and *
are not present in the function definition, arguments may be passed to a function by position or by keyword.
4.7.3.2. Positional-Only Parameters
Positional-only parameters are placed before a /
(forward-slash).
4.7.3.3. Keyword-Only Arguments
place an *
in the arguments list just before the first keyword-only parameter.
4.7.3.4. Function Examples
1 | def standard_arg(arg): |
1 | passed by position |
These separaters are used to avoid ambiguity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22def foo(name , **kwds):
print(name)
return 'name' in kwds # this can never be True
0,a=1,name=3) foo(
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'
3) foo(name=
3
False
0,name=3) foo(
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'
def fo(name , / , **kwds):
print(name)
return 'name' in kwds
0,name=3) fo(
0
True4.7.3.5. Recap
- Use positional-only if you want the name of the parameters to not be available to the user. This is useful when parameter names have no real meaning, if you want to enforce the order of the arguments when the function is called or if you need to take some positional parameters and arbitrary keywords.
- Use keyword-only when names have meaning and the function definition is more understandable by being explicit with names or you want to prevent users relying on the position of the argument being passed.
- For an API, use positional-only to prevent breaking API changes if the parameter’s name is modified in the future.
4.7.4. Arbitrary Argument Lists
variadic arguments will be last in the list of formal parameters
Any formal parameters which occur after the
*args
parameter are ‘keyword-only’ arguments1
2
3
4
5
6
7def concat(*args, sep="/"):
return sep.join(args)
...
"earth", "mars", "venus") concat(
'earth/mars/venus'
"earth", "mars", "venus", sep=".") concat(
'earth.mars.venus'4.7.5. Unpacking Argument Lists
write the function call with the
*
operator to unpack the arguments out of a list or tupleIn the same fashion, dictionaries can deliver keyword arguments with the
**
operator
1 | 1 , 10) tp = ( |
4.7.6. Lambda Expressions
Small anonymous functions can be created with the
lambda
keyword.1
lambda parameter1 , parameter2 , ... : an expression
Lambda functions can be used wherever function objects are required.
They are syntactically restricted to a single expression. And they are just syntactic sugar.
1 | 1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')] pairs = [( |
1 | lambda *,k1 : k1 # the arguments' type separator works, they are just syntactic sugar. x = |
4.7.7. Documentation Strings
The first line should always be a short, concise summary of the object’s purpose.
This line should begin with a capital letter and end with a period
.
.If there is a second line, the second line should be blank, visually separating the summary from the rest of the description.
The following lines should be one or more paragraphs describing the object’s calling conventions, its side effects, etc
The first non-blank line after the first line of the string determines the amount of indentation for the entire documentation string.(Just a convention)
use
__doc__
to check the documentation strings of a function1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23def DOC():
'''Test documentation string
the first non-blank line
the second non-blank line'''
pass
DOC.__doc__
'Test documentation string\n\n\tthe first non-blank line\n\tthe second non-blank line'
print(DOC.__doc__)
Test documentation string
the first non-blank line
the second non-blank line
print.__doc__) print(
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.4.7.8. Function Annotations
Function annotations are completely optional metadata information about the types used by user-defined functions
Annotations are stored in the
__annotations__
attribute of the function as a dictionary and have no effect on any other part of the function.Parameter annotations are defined by a colon after the parameter name, followed by an expression evaluating to the value of the annotation.
f(arg : type)
, position argumentf(arg : type = value)
, kwd argumentf() -> type
, return value
1
2
3
4
5
6
7
8
9def f(ham: str, eggs: str = 'eggs') -> str:
"Annotations:", f.__annotations__) print(
"Arguments:", ham, eggs) print(
return ham + ' and ' + eggs
...
'spam') f(
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'4.8. Intermezzo: Coding Style
- Use 4-space indentation, and no tabs.
- Wrap lines so that they don’t exceed 79 characters.
- Use blank lines to separate functions and classes, and larger blocks of code inside functions.
- When possible, put comments on a line of their own.
- Use docstrings.
- Use spaces around operators and after commas, but not directly inside bracketing constructs:
a = f(1, 2) + g(3, 4)
. - Name your classes and functions consistently; the convention is to use
UpperCamelCase
for classes andlowercase_with_underscores
for functions and methods. Always useself
as the name for the first method argument. - Don’t use fancy encodings if your code is meant to be used in international environments.
- Likewise, don’t use non-ASCII characters in identifiers if there is only the slightest chance people speaking a different language will read or maintain the code.