定义(关键字def):
编程语言中函数定义:函数是逻辑结构化和过程化的一种编程方法(函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可)
函数特性:
1.减少重复代码
2.使程序变得可扩展
3.使程序变得易维护
格式:
1 def func1(): # 函数名func1 2 """这里是注释""" 3 代码块 4 return 值
注:过程是缺少返回值的函数(在python中,过程实际是返回值为None的函数);想要查看返回值,可以将调用函数的结果赋给一个变量

1 import time 2 3 4 def logger(): 5 """追加内容至文档a中,并标识时间""" 6 time_format = '%Y-%m-%d %X' 7 time_current = time.strftime(time_format) 8 with open('a.txt', "a+", encoding='utf-8') as f: 9 f.write(f'{time_current} Yesterday once more-昨日重现\n') 10 f.close() 11 def test1(): 12 print("In the test1") 13 logger() 14 def test2(): 15 print("In the test2") 16 logger() 17 def test3(): 18 print("In the test3") 19 logger() 20 test1() # 调用函数test1 21 test2() # 调用函数test2 22 test3() # 调用函数test3
可以返回的值:
1.什么都不写:返回None
2.return 0:返回0
3.return 1,’hello’,[‘sjc’,’wk’],{‘name’:’sjc’}:返回元组(1,’hello’,[‘sjc’,’wk’],{‘name’:’sjc’})
为什么要有返回值:后续其他逻辑可能会根据返回值的不同进行不一样的操作

def test1(): print('in the test1') def test2(): print('in the test2') return 0 def test3(): print('in the test3') return 1, 'hello', ['sjc', 'wk'], {'name': 'sjc'} x = test1() y = test2() z = test3() print(x, '\n', y, '\n', z, sep='')

1 in the test1 2 in the test2 3 in the test3 4 None 5 0 6 (1, 'hello', ['sjc', 'wk'], {'name': 'sjc'})
形参与实参:
形参:变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
实参:可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
注意:传参时实参与形参是一一对应的(位置参数),若想不按顺序传入,需要用 传参=实参(关键字参数)的方式,但是,关键字参数必须位于位置参数后方
默认参数:
调用函数的时候,默认参数非必须传递,不传递时则取默认值,传递则取传递值
参数组:
形参以*开始+一个变量名,一般为*args(规范,尽量别改),会把所有传入参数放入一个元组,只接收位置参数
想传入字典呢?试试**kwargs且用关键字参数传参(或者用**+字典的方式传参)
再试试参数组与参数组、形参、默认参数结合
注意:参数组尽量往后放

1 def test(x, y): 2 print(x) 3 print(y) 4 5 6 test(1, 2) 7 test(y="关键参数y", x='关键参数x') 8 9 10 def test2(x, y='我是默认参数'): 11 print(x) 12 print(y) 13 14 15 test2(1) 16 test2(y='赋值后默认参数会改', x=4) 17 18 19 def test3(*args): 20 print(args) 21 22 23 test3(1, 2, 4, 8, 9) 24 25 26 # 传入参数个数不固定时 27 # *args:把N个位置参数转换成元组的方式 28 def test4(x, *args): 29 print(x) 30 print(args) 31 32 33 test4(5, 6, '参数不固定', 8, 10) 34 test4(*[5, 6, '参数不固定', 8, 10]) # args = tuple([5, 6, '参数不固定', 8, 10]) 35 36 37 # 把N个关键字参数转换成字典的方式 38 def test5(**kwargs): 39 print(kwargs) 40 print(kwargs['name']) # 取字典中key为name的value(key不存在会报错) 41 42 43 test5(name='sjc', age=18) 44 test5(**{'name': 'sjc', 'age': 18, 'size': 'unknown'}) 45 46 47 def test6(name, age=18, *args, **kwargs): 48 print(name) 49 print(age) 50 print(args) 51 print(kwargs) 52 53 54 test6('SJC', 12, 5, hobby='game')

1 2 关键参数x 关键参数y 1 我是默认参数 4 赋值后默认参数会改 (1, 2, 4, 8, 9) 5 (6, '参数不固定', 8, 10) 5 (6, '参数不固定', 8, 10) {'name': 'sjc', 'age': 18} sjc {'name': 'sjc', 'age': 18, 'size': 'unknown'} sjc SJC 12 (5,) {'hobby': 'game'} Process finished with exit code 0
局部变量:
只在函数中生效(在函数内部代码块位置定义的变量)/可用global将局部变量改为全局变量(尽量别用)
全局变量:
在整个代码顶层定义的变量
当全局变量与局部变量同名时:在局部变量内修改变量值,当变量是字符串或整型时,调用函数是修改后的值,但调用结束后全局变量是不变的(在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用);当变量是列表等类型时,使用局部变量修改列表内某些值,调用函数结束后全局变量也随之改变。

1 # def change_name(name): 2 # print('before change', name) 3 # name = 'SJC' # 这个函数就是这个变量的作用域 4 # print('after change', name) 5 # 6 # name = 'sjc' 7 # change_name(name) 8 # print(name) 9 10 name = 'SJC' 11 name1 = [1, 2, 3] 12 13 14 def change_name(): 15 name = 'sjc' 16 name1[0] = 8 17 print(name, name1) 18 19 20 print(name, name1) 21 change_name() 22 print(name, name1)

1 SJC [1, 2, 3] 2 sjc [8, 2, 3] 3 SJC [8, 2, 3]
递归:
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
递归特性:
1.必须有一个明确的结束条件
2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

1 def calc(n): 2 if n/2 > 0: 3 print(n) 4 return calc(int(n/2)) 5 print(n) 6 7 8 calc(10)

1 10 2 5 3 2 4 1 5 0
函数式编程:知乎“什么是函数式编程思维?”
高阶函数:
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

1 def add(a, b, f): 2 return f(a)+f(b) 3 4 5 res = add(3, -6, abs) 6 print(res)
上例输出为 9