为什么要用函数?
1、减少代码量
2、保持一致性
3、易维护
一、函数的定义和使用
1
2
3
4
5
6
|
def
test(参数):
...
函数体
...
return
返回值
|
函数的定义:
def:表示函数的关键字
函数名:以后可以根据函数名调用函数,test可以作函数名
函数体:中间可以做一系列的运算
参数:为函数提供数据
返回值(return):当函数执行完毕后,可以给调用者返回数据。 多个返回元组形式,单个为原形式
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 def test(x): # x代表形参 2 ''' 3 2*x+1 4 :param x:整形数字 5 :return:返回计算结果 6 ''' 7 y = 2*x+1 8 return y 9 print(test) # 打印test的内存地址 10 p = test(3) # test()表示运行,函数名加小括号,要重新赋值变量 11 print(p)
形参和实参
形参不占用内存空间,调用时才会占用内存,在调用结束后,才会被释放。实参是给实参进行赋值
1 def test(x): # x代表形参 2 ''' 3 2*x+1 4 :param x:整形数字 5 :return:返回计算结果 6 ''' 7 y = 2*x+1 8 return y 9 p = test(3) # test()表示运行名为test函数,3代表实参,给x进行赋值 10 print(p)
位置参数:位置要一一对应,不能缺也不能多且不能给同一个形参赋予多个值(会报错)
关键字参数:位置无需固定,但是缺一不行多一也不行
位置参数必须在关键字参数的左边
1 def test(x,y,z):#x=1,y=2,z=3 2 print(x) 3 print(y) 4 print(z) 5 6 # 位置参数,必须一一对应,缺一不行多一也不行 7 test(1,2,3) 8 9 # 关键字参数,无须一一对应,缺一不行多一也不行 10 test(y=1,x=3,z=4) 11 12 # 位置参数必须在关键字参数左边 13 test(1,y=2,3)#报错 14 test(1,3,y=2)#报错 15 test(1,3,z=2) 16 test(1,3,z=2,y=4)#报错 17 test(z=2,1,3)#报错 18 19 位置参数和关键字参数一起也不能给同一参数赋多个值(会报错) 20 不能缺也不能多
默认参数 如果之前给了一个值一个参数,再赋予这个值一个参数,则这个值原有的参数会被覆盖掉
def handle(x, type='mysql'): print(x) print(type) handle('hello') # 调用handle函数,x赋值为hello,type有了默认参数 handle('hello', type='sqlite') # x赋值,type用关键字重新赋值 handle('hello', 'sqlite') # 用位置一一对应关系赋值,覆盖type原来的值 结果 hello mysql hello sqlite hello sqlite
参数组(*args列表,**kwargs字典) 非固定长度参数 *args是以元祖的形式表达
def test(x, *args): print(x) print(args) test(1) # 只传入x的值,*args默认为空,元组形式 test(1, 2, 3, 4, 5) # 传入x的值后,位置关系对应后,2 3 4 5对应*args以元组形式表达 test(1, {"name": "alex"}) # 传入x的值后,有一个字典,整体传入 test(1, ["x", "y", "z"]) # 传入x的值后,有一个列表,整体传入 test(1,*["x","y","z"]) # 传入x的值后,列表前面加了个*,则表示遍历,逐一出现表达 test(1,*("x","y","z")) # 同上,注意表现形式
结果
1
()
1
(2, 3, 4, 5)
1
({'name': 'alex'},)
1
(['x', 'y', 'z'],)
1
('x', 'y', 'z')
1
('x', 'y', 'z')
**kwargs
def test(x, **kwargs): print(x) print(kwargs) 以字典的形式表达 test(1, y=2, z=3) #y,z为key 后面均为值 test(1,y=2,z=3,z=4) #会报错:一个参数不能传俩个值 结果 1 {'y': 2, 'z': 3}
*args,**kwargs同时存在,扩展性
def test(x,*args,**kwargs): print(x) print(args,args[-1]) print(kwargs,kwargs.get('y')) # test(1,1,2,1,1,11,1,x=1,y=2,z=3) #报错,x传了多个值 test(1, 1, 2, 1, 1, 11, 1, y=2, z=3) #1传给x,中间位置参数给*args,关键字参数给**kwargs test(1,*[1,2,3],**{'y':1}) #1传给x,*[1,2,3]传给*args遍历传,**{'y':1}传给**kwargs 结果 1 (1, 2, 1, 1, 11, 1) 1 {'y': 2, 'z': 3} 2 1 (1, 2, 3) 3 {'y': 1} 1
全局变量(大写)
定义:没有缩进的变量
局部变量(小写)
定义:子程序下定义的变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
name = 'lhf' # 这里就指全局变量 def change_name(): name = '帅了一比' # 这里就指局部变量 print('change_name', name) change_name() print(name) 结果 change_name 帅了一比 lhf
global声明是全局变量,nolocal指定上一级变量
如果函数的内容无global关键字
- 有声明局部变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
NAME = ["产品经理","廖波湿"] def qupengfei(): NAME = "自己" print('我要搞', NAME) qupengfei() 结果 我要搞 自己
- 无声明局部变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 NAME = ["产品经理","廖波湿"] 2 def qupengfei(): 3 NAME.append('XXOO') 4 print('我要搞', NAME) 5 qupengfei()
如果函数的内同有global关键字
- 有声明局部变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
NAME = ["产品经理","病毒尖儿"] def qupengfei(): global NAME NAME = "自己" print('我要搞', NAME) qupengfei() 结果 我要搞 ['产品经理', '病毒尖儿'] # 错误示例 NAME = ["产品经理","病毒尖儿"] def qupengfei(): NAME = "自己" # 有局部变量,报错 global NAME # 不能在下面 print('我要搞', NAME) qupengfei()
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
NAME = ["产品经理","病毒尖儿"] def qupengfei(): global NAME NAME = "自己" print('我要搞', NAME) qupengfei() 结果 我要搞 ['产品经理', '病毒尖儿'] # 错误示例 NAME = ["产品经理","病毒尖儿"] def qupengfei(): NAME = "自己" # 有局部变量,报错 global NAME # 不能在下面 print('我要搞', NAME) qupengfei()
- 无声明局部变量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
NAME = ["产品经理", "病毒尖儿"] def qupengfei(): global NAME NAME = ["三毛"] NAME.append('XXOO') print('我要搞', NAME) qupengfei() 结果 我要搞 ['三毛', 'XXOO']
优先读取局部变量,能读取全局变量,但无法对全局变量重新赋值NAME=“fff”,但是对于可变类型,可以对内部元素进行操作
如果函数中有glabal关键字,变量本质上就是全局的那个变量,可读取可赋值 NAME=“fff”
递归函数
自己调用自己的函数,则为递归
特性:必须有一个明确的结束条件
每次进入深一层递归时,问题规模都应有所减少
def calc(n): print(n) if int(n / 2) == 0: return n # 当上面的条件成立后一个真值,返回到函数 res = calc(int(n / 2)) print(n,res) return res # 返回res的值,要将真值一层一层传递回去 calc(10)
匿名函数 用lambda去定义
例1:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 def calc(x): 2 return x+1 3 res=calc(10) 4 print(res) # 输出结果 5 print(calc) # 输出calc这个函数的内存地址 6 print(lambda x:x+1)# 输出lambda这个表达式的内存地址 7 func = lambda x:x+1# x代表形参,x+1为返回值 8 print(func(10)) # 给lambda表达式传入值,输出结果 9 10 """ 11 结果 12 11 13 11 14 <function <lambda> at 0x000001F6D84897B8> 15 11 16 """
例2:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
name = "alex" def change_name(x): return name+"_sb" res = change_name(name) print(res) func = lambda x:x+"_sb" res = func(name) print(res)
函数式编程
函数接收的参数是一个函数名
高阶函数
1、把函数当作一个参数传给另一个函数
2、返回值中包含参数
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 def bar(): 2 print('from bar') 3 def foo(): 4 print('from foo') 5 return bar 6 n = foo() 7 n()
转自:
python之函数介绍及使用 - 病毒尖er - 博客园
http://www.cnblogs.com/leguan1314/articles/6116928.html