Contents

Python教程-其他流程控制工具

本系列为作者在官网学习python时做的笔记,详见python官网

python标准库官方文档,查阅标准库相关的内容

python语言参考,查看python语法,该文档是简洁的,但试图做到准确和完整。非必要的内建对象类型和内建函数、模块的语义描述在 Python 标准库 中。

标准库和语言参考涵盖了python的所有内容,他们是互补的,如果在语言参考中没有找到需要的内容那么就一定在便准库文档中。

if 语句

if 语句包含零个或多个 elif 子句及可选的 else 子句。

for 语句

python中只有for in

1
2
3
4
5
6
7
8
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
...     print(w, len(w))
...
cat 3
window 6
defenestrate 12

循环遍历该集合的副本或创建新集合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Strategy:  Iterate over a copy
for user, status in users.copy().items():
    if status == 'inactive':
        del users[user]

# Strategy:  Create a new collection
active_users = {}
for user, status in users.items():
    if status == 'active':
        active_users[user] = status

range() 函数

内置函数 range()生成算术级数:

1
2
3
4
5
6
7
8
>>> for i in range(5):
...     print(i)
...
0
1
2
3
4

给定的终止数值并不在要生成的序列

两个参数时,第一个参数是开始值,第二个参数是终止值

三个参数时,第三个参数是步长可以是负数

1
2
3
4
5
6
7
8
range(5, 10)
   5, 6, 7, 8, 9

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

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

range() 所返回的对象在许多方面表现得像一个列表,但实际上却并不是。我们称这样对象为 iterable

break 和 continue 语句,以及循环中的 else 子句

break 语句用于跳出最近的 for 或 while 循环.

else 子句在循环耗尽了可迭代对象 (使用 for) 或循环条件变为假值 (使用 while) 时被执行,但不会在循环被 break 语句终止时被执行。

continue 继续循环中的下一次迭代:

pass 语句

pass 语句什么也不做,这通常用于创建最小的类:

1
2
3
>>> class MyEmptyClass:
...     pass
...

定义函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
>>> 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

关键字 def 引入一个函数 定义。它必须后跟函数名称和带括号的形式参数列表。构成函数体的语句从下一行开始,并且必须缩进。

函数体的第一个语句可以(可选的)是字符串文字;这个字符串文字是函数的文档字符串或 docstring 。

函数的 执行 会引入一个用于函数局部变量的新符号表。函数中所有的变量赋值都将存储在局部符号表中;变量引用会首先在局部符号表中查找,然后是外层函数的局部符号表,再然后是全局符号表,最后是内置名称的符号表。 因此,全局变量和外层函数的变量不能在函数内部直接赋值(除非是在 global 语句中定义的全局变量,或者是在 nonlocal 语句中定义的外层函数的变量),但是它们可以被引用。

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用 按值调用 来传递的(其中的 值 始终是对象的 引用 而不是对象的值)。 当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。

函数定义会将函数名称与函数对象在当前符号表中进行关联。 解释器会将该名称所指向的对象识别为用户自定义函数。 其他名称也可指向同一个函数对象并可被用来访问访函数:

1
2
3
4
5
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

没有 return 语句的函数也会返回一个值,这个值称为 None (它是内置名称),可以通过print打印

1
2
3
>>> fib(0)
>>> print(fib(0))
None

函数定义的更多形式

参数默认值

对一个或多个参数指定一个默认值:

1
2
3
def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        ...

默认值在 定义过程 中在函数定义处计算的,计算默认值只会执行一次(对于引用类型则指向的对象不变),所以下面这个实例会打印 5

1
2
3
4
5
6
7
i = 5

def f(arg=i):
    print(arg)

i = 6
f()
1
2
3
4
5
6
7
def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

这将打印出

1
2
3
[1]
[1, 2]
[1, 2, 3]

关键字参数

使用形如 kwarg=value 的 关键字参数 来调用函数。

关键字参数必须跟随在位置参数(非关键字参数)的后面。传递的所有关键字参数必须与函数接受的其中一个参数匹配,它们的顺序并不重要。不能对同一个参数多次赋值。

最后一个形参为 **name 的时,它会接收一个字典 ,包含除了与已有形参相对应的关键字参数以外的所有关键字参数。 它可以与一个形式为 *name,接收一个包含除了已有形参列表以外的位置参数的 元组 的形参组合使用 (*name 必须出现在 **name 之前。)

特殊参数

函数调用时的参数只有位置参数或是显式的关键字参数。

函数的定义看起来可以像是这样:

1
2
3
4
5
6
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |        Positional or keyword   |
        |                                - Keyword only
         -- Positional only

/仅用于分割仅位置参数的形参,*仅用于分割仅关键字形参

*name就是*

任意的参数列表

可变参数 将在形式参数列表的末尾,因为它们收集传递给函数的所有剩余输入参数。出现在 *args 参数之后的任何形式参数都是 ‘仅限关键字参数’,所以通常将 *后面的参数都设置为有默认值的形参:

1
2
3
4
5
6
7
>>> def concat(*args, sep="/"):
...     return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

解包参数列表

参数已经在列表或元组中,使用 * 操作符解包参数:

1
2
3
4
5
>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]

同样的方式,字典可使用 ** 操作符 来提供关键字参数:

1
2
3
4
5
6
7
8
>>> def parrot(voltage, state='a stiff', action='voom'):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

Lambda 表达式

可以用 lambda 关键字来创建一个小的匿名函数:

1
2
3
4
5
6
def make_incrementor(n):
    # 用 :来分割参数和返回值
    return lambda x: x + n

f = make_incrementor(42)
f(0)

函数标注

函数标注 是用户自定义函数中使用的类型的完全可选元数据信息。以字典的形式存放在函数的 annotations 属性中,并且不会影响函数的任何其他部分。

形参标注的定义方式是在形参名后加冒号,后面跟一个表达式,该表达式会被求值为标注的值。

返回值标注的定义方式是加组合符号 ->,后面跟一个表达式,该标注位于形参列表和表示 def 语句结束的冒号之间

1
2
3
4
5
6
7
8
9
>>> def f(ham: str, eggs: str = 'eggs') -> str:
...     print("Annotations:", f.__annotations__)
...     print("Arguments:", ham, eggs)
...     return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'

对于要求传入迭代对象的参数

可以在调用函数的时候在实参中使用推导式以及lambda表达式来现场生成对象,比如

1
nx.draw_networkx(...,labels={n:prefix+n for n in G})

Functools

functools 模块应用于高阶函数,即参数或(和)返回值为其他函数的函数。详见官方文档

functools.partial(func, /, *args, **keywords)

返回一个新的 部分对象,当被调用时其行为类似于 func 附带位置参数 args 和关键字参数 keywords 被调用。

官方文档

1
2
3
4
def f(m,n):
    return m*n
re=partial(f,3)
print(re(4))#12
 |