Skip to content

Python 学习笔记 4. 流程控制

🏷️ Python Python 学习笔记

if

python
>>> 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

python
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
...     print(w, len(w))
...
cat 3
window 6
defenestrate 12
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

range()

python
>>> for i in range(5):
...     print(i)
...
0
1
2
3
4
>>> for i in range(5, 10):
...     print(i)
...
5
6
7
8
9
>>> for i in range(0, 10, 3):
...     print(i)
...
0
3
6
9
>>> for i in range(-10, -100, -30):
...     print(i)
...
-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
>>> print(range(10))
range(0, 10)
>>> list(range(5))
[0, 1, 2, 3, 4]

break & continue & 循环中的 else

python
>>> 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
>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
...
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9

pass

python
>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt
>>> class MyEmptyClass: # 创建最小的类
...     pass
...
>>> def initlog(*args): # 作为一个函数或条件子句体的占位符
...     pass   # Remember to implement this!
...

定义函数

python
>>> 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
>>> fib
<function fib at 0x00000000005CC1E0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
>>> fib(0)

>>> print(fib(0)) # 没有 return 的函数返回 None

None
>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

参数默认值

python
>>> 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)
...
>>> ask_ok('Do you really want to quit?')
Do you really want to quit?x
Please try again!
Do you really want to quit?x
Please try again!
Do you really want to quit?x
Please try again!
Do you really want to quit?x
Please try again!
Do you really want to quit?x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in ask_ok
ValueError: invalid user response
>>> ask_ok('OK to overwrite the file?', 2)
OK to overwrite the file?x
Please try again!
OK to overwrite the file?x
Please try again!
OK to overwrite the file?x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in ask_ok
ValueError: invalid user response
>>> ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
OK to overwrite the file?x
Come on, only yes or no!
OK to overwrite the file?x
Come on, only yes or no!
OK to overwrite the file?x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in ask_ok
ValueError: invalid user response

默认值是在 定义过程 中在函数定义处计算的。

python
>>> i = 5
>>> def f(arg=i):
...     print(arg)
...
>>> i = 6
>>> f()
5

重要警告

默认值只会执行一次。这条规则在默认值为可变对象(列表、字典以及大多数类实例)时很重要。

python
>>> def f(a, L=[]):
...     L.append(a)
...     return L
...
>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]
>>> print(f(3))
[1, 2, 3]

说起来,这也许就是 C# 中限制了参数的默认值必须是编译时常量的原因。

如果不想要在后续调用之间共享默认值

python
>>> def f(a, L=None):
...     if L is None:
...         L = []
...     L.append(a)
...     return L
...
>>> print(f(1))
[1]
>>> print(f(2))
[2]
>>> print(f(3))
[3]

关键字参数

类似于 C# 中的命名参数。

python
>>> 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, "!")
...
>>> parrot(1000)                                          # 1 positional argument
-- This parrot wouldn't voom if you put 1000 volts through it.
-- Lovely plumage, the Norwegian Blue
-- It's a stiff !
>>> parrot(voltage=1000)                                  # 1 keyword argument
-- This parrot wouldn't voom if you put 1000 volts through it.
-- Lovely plumage, the Norwegian Blue
-- It's a stiff !
>>> parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
-- This parrot wouldn't VOOOOOM if you put 1000000 volts through it.
-- Lovely plumage, the Norwegian Blue
-- It's a stiff !
>>> parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
-- This parrot wouldn't VOOOOOM if you put 1000000 volts through it.
-- Lovely plumage, the Norwegian Blue
-- It's a stiff !
>>> parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
-- This parrot wouldn't jump if you put a million volts through it.
-- Lovely plumage, the Norwegian Blue
-- It's bereft of life !
>>> parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword
-- This parrot wouldn't voom if you put a thousand volts through it.
-- Lovely plumage, the Norwegian Blue
-- It's pushing up the daisies !

错误的调用:

python
>>> parrot()                     # required argument missing
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: parrot() missing 1 required positional argument: 'voltage'
>>> parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument

  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> parrot(110, voltage=220)     # duplicate value for the same argument
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: parrot() got multiple values for argument 'voltage'
>>> parrot(actor='John Cleese')  # unknown keyword argument
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: parrot() got an unexpected keyword argument 'actor'

元组形参(*name)和字典形参(**name)的组合使用:

python
>>> 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)
...     for kw in keywords:
...         print(kw, ":", keywords[kw])
...
>>> cheeseshop("Limburger", "It's very runny, sir.",
...            "It's really very, VERY runny, sir.",
...            shopkeeper="Michael Palin",
...            client="John Cleese",
...            sketch="Cheese Shop Sketch")
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch

可变参数

python
>>> def write_multiple_items(file, separator, *args): # 一般可变参数放在最后
...     file.write(separator.join(args))
...
>>> def concat(*args, sep="/"): # 可变参数 后的参数必须是 关键字参数
...     return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

解包参数列表

python
>>> 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]

使用 ** 操作符解包 字典参数 成 关键字参数。

python
>>> 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 表达式

python
>>> def make_incrementor(n):
...     return lambda x: x + n # 用 lambda 关键字来创建一个小的匿名函数
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1]) # 传递一个小函数作为参数
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

文档字符串

Python 解析器不会从 Python 中删除多行字符串文字的缩进。

默认约定:文档字符串第一行 之后 的第一个非空行确定整个文档字符串的缩进量。

python
>>> 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.

函数标注

指定函数的入参和回参的类型。

python
>>> 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'>, 'eggs': <class 'str'>, 'return': <class 'str'>}
Arguments: spam eggs
'spam and eggs'

编码风格

PEP 8 已经成为大多数项目所遵循的风格指南。

  • 使用 4 个空格缩进,不要使用制表符。

  • 换行,使一行不超过 79 个字符。

  • 使用空行分隔函数和类,以及函数内的较大的代码块。

  • 如果可能,把注释放到单独的一行。

  • 使用文档字符串。

  • 在运算符前后和逗号后使用空格,但不能直接在括号内使用: a = f(1, 2) + g(3, 4)

  • 以一致的规则为你的类和函数命名;按照惯例应使用 UpperCamelCase 来命名类,而以 lowercase_with_underscores 来命名函数和方法。始终应使用 self 来命名第一个方法参数。

  • 如果你的代码旨在用于国际环境,请不要使用花哨的编码。Python 默认的 UTF-8 或者纯 ASCII 在任何情况下都能有最好的表现。

  • 同样,哪怕只有很小的可能,遇到说不同语言的人阅读或维护代码,也不要在标识符中使用非 ASCII 字符。