4. 其他控制流程工具
接下来会用到出了while之外的更多流程控制语句.
4.1 if 语句
与 if
相关的有 if
else
elif
语句, 它们组合起来无非就是:
if 1==1:
print("Yes")
if 1==1:
print("Yes")
else:
print("No")
if 1==1:
print("Yes")
elif 1==2:
print("Yes1")
elif 1==3:
print("Yes2")
if 1==1:
print("Yes")
elif 1==2:
print("Yes1")
elif 1==3:
print("Yes2")
else:
print("No")
其中elif 可以无限在里面加
4.2 for 语句
使用for语句进行循环的时候最好使用其复制进行操作, 因为如果在循环里对循环对象进行更改, 很可能会造成循环无限的循环下去.
Test.py:
n = [1, 2, 3, 4]
for i in n[:]:
n.append(5)
print(n)
运行结果:
[1, 2, 3, 4, 5, 5, 5, 5]
***Repl Closed***
4.3 range() 函数
range()
函数用于生成一连串的数字序列, range可以以任意数字开头, 或者以指定的幅度增加.
Test.py:
n = list(range(5))
x = list(range(3, 5))
y = list(range(3, 10, 2))
z = list(range(10, 5, -1))
print(n)
print(x)
print(y)
print(z)
运行结果:
[0, 1, 2, 3, 4]
[3, 4]
[3, 5, 7, 9]
[10, 9, 8, 7, 6]
***Repl Closed***
4.4 break 和 continue 语句 循环中的else 子句
与一般语言不同的是, python的 for
循环可以带有一个 else
子句, 在循环正常完成(不是被break中断)的时候被执行, .
Test.py:
for i in range(5):
pass
else:
print("Yes1")
for i in range(5):
if i == 3:
break
else:
print("Yes2")
运行结果:
Yes1
***Repl Closed***
4.5 pass语句
pass语句什么也不做, python不像其他语言, 当不需要执行的时候可以忽略不写, python如果if成功后不加相应执行代码就会报错, 此时可以使用pass来代替此时的逻辑.
Test.py:
if 1==1:
pass
else:
print("Yes")
运行结果:
***Repl Closed***
4.6 定义函数
定义函数, 定义一个斐波那契数列的函数:
Test.py:
def fib(n):
a = 0
b = 1
print(a)
for i in range(n):
a, b = b, a+b
print(a)
fib(5)
运行结果:
0
1
1
2
3
5
***Repl Closed***
函数定义的格式: "def + 函数名 + ( + 变量名 + ) + : ", 函数的逻辑部分必须相对于函数的定义缩进.
python 中的函数可以通过等号赋给另一个名称, 函数名称具有解释器将其识别为用户定义函数的类型.
Test.py:
def test(n):
print(n)
test1 = test
test1(12)
print(type(test))
print(type(test1))
运行结果:
12
<class 'function'>
<class 'function'>
***Repl Closed***
4.7 函数定义的更多形式
函数的参数是可变的, 个数, 默认值等.
4.7.1 参数默认值
可以设定参数的默认值, 当没有参数传入时, 则使用默认值代替.
Test.py:
def test(x, y, z = 3):
print(x, y, z)
test(1, 2)
test(1, 2, 4)
运行结果:
1 2 3
1 2 4
***Repl Closed***
需要注意的是: 有默认值的参数必须放在结尾
.
默认值是在定义过程中在函数定义处计算的, 这句话的意思以我的理解, 当函数被定义的时候是从代码的开始到结尾从上到下的顺序去获取值的参数的, 所以以下例子可以看到值采用的是顶部的变量, 并且在后面进行更改也不会使其变化.
Test.py:
y = 1
def test(x = y):
print(x)
print(y)
y = 2
test()
print(y)
运行结果:
1
2
2
***Repl Closed***
默认值的初始化只会执行一次, 所以当类似列表这种默认值后期变化了的话就会真的变化, 可能是因为列表存的是它的地址.
Test.py:
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
运行结果:
[1]
[1, 2]
[1, 2, 3]
***Repl Closed***
官方文档中对此给出了一个解决方案——解决防止后续调用共享值.
Test.py:
def f(a, L = None):
if L == None:
L = []
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
运行结果:
[1]
[2]
[3]
***Repl Closed***
4.7.2 关键字参数
可以使用关键字来确定参数的位置, 这样就不用按照位置来传递参数.
Test.py:
def f(x, y):
print(x, y)
f(1, 2)
f(y = 2, x = 1)
运行结果:
1 2
1 2
***Repl Closed***
还有一些需要注意的点:
- 含有默认值的函数的参数, 默认值的参数必须在没有默认值的后面, 不然会报
SyntaxError: non-default argument follows default argument
的错误. - 因为使用了关键字参数, 但是位置还是有限制的, 传递参数时没有使用关键字的参数必须在使用关键字参数的前面.
4.7.3 任意的参数列表
参数中还可以传递 *name
和 **name
这类可变长的.
Test.py:
def f(x, *y):
print(x)
print(y)
f(1, 2, 3, 4)
运行结果:
1
(2, 3, 4)
***Repl Closed***
可以看到函数的定义中只有二个参数, 但是传递的却有4个参数, 后面的三个参数作为元组传递给了y, 这就是它的作用.
Test.py:
def f(x, **y):
print(x)
for key, value in y.items():
print(key, value)
f(1, y1 = 2, y2 = 3, y3 = 4)
运行结果:
1
y1 2
y2 3
y3 4
***Repl Closed***
同样的使用 **y
的参数包含了传入的几个键值对.
*name
和 **name
必须在函数参数的末尾(可在有默认值参数的前面), 而且 *name
必须比 **name
前.
4.7.4 解包参数列表
当我们需要的参数在元组或是列表中的时候, 单个的取出来是比较麻烦的, 可以通过 *
来进行解包.
Test.py:
args = [3, 6]
print(list(range(args[0], args[1])))
print(list(range(*args)))
运行结果:
[3, 4, 5]
[3, 4, 5]
***Repl Closed***
同样还有一个 **name
也能把字典传递.
Test.py:
def TestFunction(p1, p2):
print(p1, p2)
args = {"p1":3, "p2":6}
TestFunction(**args)
运行结果:
3 6
***Repl Closed***
4.7.5 Lambda 表达式
Lambda
关键字是用于创建匿名函数的.
Test.py:
f = lambda x:x + 1
print(f(1))
运行结果:
2
***Repl Closed***
大致的语法就是 lambda
关键字 + 涉及到的变量(用逗号分隔)
+ :
+ 逻辑
4.7.6 文档字符串
文档字符串用于说明函数的一些信息. 可以通过函数的 __doc__
属性获取到.
Test.py:
def function():
"""title
detail
"""
pass
def functionNone():
pass
print(function.__doc__)
print(functionNone.__doc__)
运行结果:
title
detail
None
***Repl Closed***
没有定义的函数, 其 __doc__
的值则是None.
4.7.7 函数标注
函数的 __annotations__
属性中以字典的方式存有函数参数类型和返回值的类型. 对于参数可以采用参数后面 + :
+ 类型
以添加, 对于返回值的类型采用 def function ()-> 类型 :
的格式.
Test.py:
def function(x:str)-> str:
return "1"
print(function.__annotations__)
运行结果:
{'x': <class 'str'>, 'return': <class 'str'>}
***Repl Closed***
其实函数标注对于函数来说其实没有具体的意义, 它不会影响函数的实际运行, 并不是说定义了类型, 其他的类型就不能接受了. 对于没有定义的参数, 实际返回的是空的字典.
对于有默认值的参数的写法就是 def function(x : str = "111"):