Python-函数编程
Posted Gulibali
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python-函数编程相关的知识,希望对你有一定的参考价值。
Python-函数编程
1,基本介绍
定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。简单一点,命令打包,然后提高了协作性,想在哪里执行就在哪里执行。
特性:
- 减少重复代码,增加复用性
- 使程序变的可拓展性
- 使程序变得易维护
- 灵活清晰
语法:
1 def functionname( parameters ): # 函数名 2 "函数_文档字符串" 3 4 functionname() # 调用函数,函数名只是指向相应地址,这个括号的作用才是要执行那段代码
也可以带参数
1 # 下面这段代码 2 a,b = 5,8 3 c = a**b 4 print(c) 5 6 # 改成用函数写 7 def calc(x,y): 8 res = x**y 9 return res # 返回函数执行结果 10 11 c = calc(a,b) # 结果赋值给c变量 12 print(c)
在定义函数的过程中,需要注意以下几点:
- 函数代码块以
def
关键词开头,一个空格之后接函数标识符名称和圆括号(),再接个冒号。 - 任何传入的参数必须放在圆括号中。
- 函数的第一行语句后可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- 使用return结束函数。默认返回None。
- return语句依然在函数体内部,不能回退缩进。直到函数的所有代码写完,才回退缩进,表示函数体结束。
2,函数参数
参数可以让你的函数更灵活,不只能做死的动作,还可以根据调用时传参的不同来决定函数内部的执行流程。
1.0 形参变量
只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
1.1 实参
可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
2.0 默认参数
1 def stu_register(name, age, country, course): 2 print(\'------学生注册信息-------\') 3 print(\'姓名:\', name) 4 print(\'age:\', age) 5 print(\'国籍:\', country) 6 print(\'课程:\', course) 7 8 stu_register("王山炮",22, \'CN\', \'python_devops\') 9 stu_register("张角春", 21, \'CN\', \'Linux\') 10 stu_register("刘老根", 25, \'CN\', \'Linux\')
这里出现了很多的 \'CN\',可以设置默认参数,就可以直接替代
def stu_register(name, age, course, country = \'CN\'): # 这里的默认参数放在最后面 print(\'------学生注册信息-------\') print(\'姓名:\', name) print(\'age:\', age) print(\'国籍:\', country) print(\'课程:\', course) stu_register("王山炮",22, \'python_devops\', \'UN\') # 如果不想使用默认参数的值,可以在最后面自定义想要的参数的值 stu_register("张角春", 21, \'Linux\') stu_register("刘老根", 25, \'Linux\')
这里的country默认参数一定要写在最后面,否则会报错,为什么呢?
因为如果设置默认参数,实际上排序上面就会造成一定的乱序,为了不乱序,python里头设定默认参数就是放在最后面,有这样的设定,就不会出现乱序啦
2.1位置参数
调用函数时根据函数定义的参数位置来传递参数称为位置参数。
2.2关键参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后
关键参数就是位置参数带有参数名,两者结合为关键参数。第二个关键参数不能在位置参数的前面。第三个不能重复赋值
3.1非固定参数 *arg(参数):元组
如果参数中出现,*users,传递的参数就可以不是固定个数参数,传过来的参数打包成元组
1 # 报警, 1个运维人员 2 def send_alert(mgs, user): 3 pass 4 5 send_alert(\'出现error,请处理\', \'xiong\') 6 7 # 报警,10个运维人员 8 def send_alert(mgs, *users): #(\'alex\', \'xxx\', \'ttt\') 9 for u in users: 10 print(\'%s->%s\'%(mgs,u)) 11 12 send_alert(\'出现error,请处理\', \'xiong, \'xxx\',\'ttt\')
# 运行结果 出现error,请处理->alex 出现error,请处理->xxx 出现error,请处理->ttt
3.2如果传过来的是list,会把他作为元组的第一个元素
# 报警,10个运维人员 def send_alert(mgs, *users): # (\'alex\', \'xxx\',\'ttt\')---> ([\'alex\', \'xxx\', \'ttt\']) for u in users: print(\'%s->%s\'%(mgs,u)) send_alert(\'出现error,请处理\', [\'xiong\', \'xxx\',\'ttt\'])
# 运行结果 出现error,请处理->[\'alex\', \'xxx\', \'ttt\']
3.3传入list,使用一个星号
不光列表,任何序列类型数据对象,比如字符串、元组都可以通过这种方式将内部元素逐一作为参数,传递给函数。而字典,则会将所有的key逐一传递进去。
1 def send_alert(mgs, *users): # (\'xiong\', \'xxx\',\'ttt\')---> (\'xiong\', \'xxx\', \'ttt\') 2 print(users) 3 for u in users: 4 print(\'%s->%s\'%(mgs,u)) 5 6 send_alert(\'出现error,请处理\', *[\'xiong\', \'xxx\',\'ttt\']) 7 8 # 运行结果 9 (\'xiong\', \'xxx\', \'ttt\') 10 出现error,请处理->xiong 11 出现error,请处理->xxx 12 出现error,请处理->ttt
1 def send_alert(mgs, *users, age): 2 for u in users: 3 print(\'%s->%s\' % (mgs, u),age) 4 send_alert(\'出现error,请处理\', \'xiong\', \'rain\', age=22) 5 6 # 如果在第四行age不指定等于22,则会报错,因为此时*users作为非固定参数,可以传多个值进去,而在第一行将age放在*users后面,则传值的时候必须带上参数,否则位置参数只能放在非固定参数的前面。 7 8 # 执行结果 9 # 出现error,请处理->xiong 22 10 # 出现error,请处理->rain 22
3.4非固定参数,**kwargs 字典
1 def func(name, degree, *args, **kwargs): 2 print(name, degree, args, kwargs) 3 func(\'xiaoqiu\', \'dortor\', \'sichuan\', \'beijing\', addr = \'shanxi\') 4 5 # 这里*args对应下面的\'sichuan\',\'beijing\'可以变为一个元组 6 # 这里**kwargs对应下面的addr = \'shanxi\' 可以变为一个字典 7 8 # 执行结果 9 # xiaoqiu dortor (\'sichuan\', \'beijing\') {\'addr\': \'shanxi\'}
4.0 “万能”参数
当*args
和**kwargs
组合起来使用,理论上能接受任何形式和任意数量的参数,在很多代码中我们都能见到这种定义方式。需要注意的是,*args
必须出现在**kwargs
之前。
1 def func(*args, **kwargs): 2 for arg in args: 3 print(arg) 4 for kwg in kwargs: 5 print(kwg, kwargs[kwg]) 6 lis = [1, 2, 3] 7 dic = {\'k1\': \'v1\', \'k2\': \'v2\'} 8 9 func(*lis, **dic) 10 11 # 执行结果 12 # 1 13 # 2 14 # 3 15 # k1 v1 16 # k2 v2
5.0 拆包
- 把元组拆成一个个,当成参数传递
- 把字典拆成一对对键值对,当成参数传递
1 ###### 拆包之前 2 def test(a,b,c=33,*args,**kwargs): 3 print(a) 4 print(b) 5 print(c) 6 print(args) 7 print(kwargs) 8 9 A = (44,55,66) 10 B = {"name":"alex","age":18} 11 12 test(11,22,33,A,B) 13 14 #### 运行结果 15 11 22 33 16 ((44, 55, 66), {\'age\': 18, \'name\': \'alex\'}) #A,B是传递的参数 17 {} #没有传入命名参数 18 19 20 21 #### 拆包之后 22 def test(a,b,c=33,*args,**kwargs): 23 print(a) 24 print(b) 25 print(c) 26 print(args) 27 print(kwargs) 28 29 A = (44,55,66) 30 B = {"name":"alex","age":18} 31 32 test(11,22,33,*A,**B) 33 34 35 #### 运行结果<br>11 36 22<br>33 37 (44, 55, 66) 38 {\'age\': 18, \'name\': \'alex\'}
3,return,返回值
1,return语句
函数外部的代码想要获取函数的执行结果,就可以在函数里用return语句把结果或对象返回。并且表示函数执行到此结束。有时候,函数不需要返回任何值,此时可以不需要return语句,它在后台默认给你返回个None,并且不给任何提示
但是更多的时候我们还是需要return一些东西。一旦函数执行过程遇到return语句,那么之后函数体内的所有代码都会被忽略,直接跳出函数体。哪怕你现在正在一个循环内。
1 def stu_register(name, age, country, course): 2 print(\'------学生注册信息-------\') 3 print(name, age, country, course) 4 5 return None # 这里的return None可加可不加,后面结果都是返回None 6 print(\'nihao\') # 即使这里还有内容没有输出,因为return在这之前,所以到return这里立即终止执行 7 # 所以,执行return的时候相当于直接跳出了函数体<br># return 1 # 这里也不执行 8 status = stu_register("王山炮",29, \'CN\', \'python_devops\') 9 print(status) 10 11 # 执行结果 12 ------学生注册信息------- 13 王山炮 29 CN python_devops 14 None
一旦函数执行过程遇到return语句,那么之后函数体内的所有代码都会被忽略,直接跳出函数体。
1 def stu_register(name, age, country, course): 2 print(\'------学生注册信息-------\') 3 print(name, age, country, course) 4 5 if age > 22: 6 return False 7 else: 8 return True 9 10 status = stu_register("王山炮",29, \'CN\', \'python_devops\') 11 print(status) 12 13 # 执行结果 14 ------学生注册信息------- 15 王山炮 29 CN python_devops 16 False
函数只能返回一个值,但是在return后面也能返回一个元组或者是一个字典
1 # 接着上面例子 2 return False,age 3 #执行结果 4 (\'False\',24) 5 6 # 再例如 7 return [False,age] 8 # 执行结果 9 [\'False\',24]
2,return返回值的类型
return可以返回什么类型的值,看下面顺便总结一下,函数可以return几乎任意python对象
1 什么都不返回,仅仅return:return 2 数字/字符串/任意数据类型: return \'hello\' 3 一个表达式:return 1+2 4 一个判断语句:return 100 > 99 5 一个变量:return a 6 一个函数调用:return func() 7 甚至是返回自己!:return self 8 多个返回值,以逗号分隔:return a, 1+2, "hello"
3,如何接收函数返回值?
我们在调用函数的时候,可以将函数的返回值保存在变量中。
1 def func(): 2 pass 3 return "something" 4 result = func()
而对于同时返回多个值的函数,需要相应个数的变量来接收,变量之间以逗号分隔:
1 def func(): 2 return 1, [2, 3], "haha" 3 4 a, b, c = func()
4,全局变量,局部变量
4.1两者的作用与关系
全局变量:定义在函数外部一级代码(没有缩进)的变量,这个变量全局都能使用(到那时要注意顺序)
局部变量:指定义在函数里面的变量,只能在局部生效。
1 name = \'beauty\' 2 def change_name(): 3 name = \'这个是里面的美女\' 4 print(name, id(name)) 5 change_name() 6 print(name, id(name)) 7 8 # 这里第一个name是一个全局变量,而第二个name是一个局部变量,它们作用的范围不一样,局部变量只对函数内部产生了影响,而全局变量对外面这个大的环境产生了影响。 9 10 #执行结果 11 这个是里面的美女 2038317628272 12 beauty 2038317363864 13 # 通过输出两个name的id可以看出,他们所指向的地址是不一样的
如果在函数内部没有定义一个局部变量,则函数会使用全局变量;
如果局部和全局变量都定义了,则函数内部会优先使用局部变量。所以两者之间存在一个由内而外的使用顺序。但是两个函数内部的局部变量又是不能共同使用的,互不干扰。
1 name = \'beauty\' 2 def change_name(): 3 # name = \'这个是里面的美女\' 4 print(name, id(name)) 5 change_name() 6 print(name, id(name)) 7 8 # 这里直接执行全局变量定义的一个name,函数里面能调用全局变量,但是函数外面不能调用局部变量 9 10 # 执行结果 11 beauty 1868336181912 12 beauty 1868336181912
4.2在函数里面修改全局变量
一般情况下不建议使用这种方法,在函数里面修改以后,如果后面要引用全局变量的话,就不知道这个全局变量是已经被修改过了
1 name = \'beauty\' 2 def change_name(): 3 global name # 引用修改全局变量一定要在局部变量之前 4 name = \'美女\' 5 print(name, \'这个是里面打印的\', id(name)) 6 change_name() 7 print(name, \'这个是外面打印的\', id(name)) 8 9 # 注意:这里的指定在函数内部的全局变量一定要在局部变量之前,否则会报错 10 # 所以,在函数里面修改全局变量,以后引用global,就把全局放在上面,不能放在下面<br> 11 #执行结果 12 美女 这个是里面打印的 2114053808040 13 美女 这个是外面打印的 2114053808040
4.3在函数里修改列表数据
无法整体修改
1 nums = [11, 22, 33, 44] 2 def change_num(): 3 nums = [11, 22, 33] 4 print(nums) 5 change_num() 6 print(nums) 7 8 # 执行结果 9 [11, 22, 33] 10 [11, 22, 33, 44] 11 12 #相当于创建了一个局部变量nums
要修改整个列表的,也要用global来修改
1 # 对列表内单独数据进行修改 2 nums = [11, 22, 33, 44] 3 def change_num(): 4 del nums[3] 5 nums[2] = 99 6 print(nums) 7 change_num() 8 print(nums) 9 10 # 执行结果 11 # [11, 22, 99] 12 # [11, 22, 99] 13 14 # 对于函数外面的nums,每个列表整体都有一个内存地址,列表里面的每个元素又都有一个 15 # 地址相对应,在函数里面调用整体的nums的内存地址是不能够被修改的,只能引用它,相当于给列表整体赋值是不能够改的,单个元素可以修改 17 # 可以修改的类型:列表,字典,集合,对象,类,里面有一串的是可以修改的 18 # 不可以修改的,数字,字符串 19
#修改整个列表 20 nums = [11, 22, 33, 44] 21 def change_num(): 22 global nums 23 nums = [\'我\', \'是\', \'在\', \'里\', \'面\', \'的\'] 24 print(nums) 25 change_num() 26 print(nums) 27 28 # 执行结果 29 [\'我\', \'是\', \'在\', \'里\', \'面\', \'的\'] 30 [\'我\', \'是\', \'在\', \'里\', \'面\', \'的\'] 31 32 # 对于修改,通用可以采用global进行修改
5,嵌套函数
嵌套函数(用于先准备一个函数,即外层函数执行完后,内层函数仍可以使用外层函数的变量),装饰器就是这种应用
注意:①函数内部可以再次定义函数。②执行需要被调用才能执行
③执行顺序,由内而外,一层一层往上
1 def line_conf(a, b): 2 def line(x): 3 return a*x + b 4 5 return line 6 7 line1 = line_conf(1, 1) 8 line2 = line_conf(4, 5) 9 print line1(5) 10 print line2(5web代码片段