矩形的面积 S = ab,只要知道任一矩形的的长和宽,就能够带入上式求得面积。这样有什么好处呢?一个公式,适用于所有矩形,一个公式,重复利用,减小了大脑的记忆负担。像这类用变量代替不变量的思想在数学中称为函数,Python中,也有相似的思想!html
在数学中,函数是指输入集合与输出集合存在一种特定的映射关系,这种映射关系能够被普遍使用。在Python中,函数是指将必定量的代码块使用一个指定的函数名经过特有的语法封装起来的代码块。python
函数优势:框架
大大减小重复代码函数
能够重复使用spa
程序具备扩展性code
程序代码结构性提升htm
如今是否是以为函数特🐮,来一块儿看看如何定义一个函数吧:blog
In [1]: def func(): # func是函数名,可随意更改 ...: print('A') # 函数的内容 ...: print('B') ...: print('C')
看完上面定义方法,其实能够发现其定义语法规则:递归
函数初始化以关键字 def 开头,以后接函数名和一对圆括号,再加一个冒号ip
函数的内容使用缩进
可是,这并非一个标准的函数写法,标准的函数应当还有一个很是重要的部分,那就是函数的说明,放在函数名的下面,用三引号引发来,例如:
In [2]: def func(): ...: ''' ...: function's description # 三引号将函数的说明引发来 ...: ''' ...: pass
函数的返回:
函数是能够将结果返回的,若是想要获取函数的执行结果,可使用关键字 return 将其返回,例如:
In [3]: def add(): ...: ''' ...: calculate a plus b ...: ''' ...: a = 5 ...: b = 6 ...: c = a + b ...: return c # 将结果c返回
函数在执行过程当中一旦执行到return语句,就会结束函数,并返回
函数中若是没有return语句,则默认执行完毕后返回 None
函数的调用:
一个函数定义完成后,必需要又相应的调用语句才可以执行,不然就和没写同样━━( ̄ー ̄*|||━━,调用方法以下:
In [4]: def tell_name(): ...: ''' ...: print your name ...: ''' ...: print('I am MinuteSheep') In [5]: tell_name() # 调用函数 I am MinuteSheep
函数的递归:在函数内部返回调用本身
你们必定作过这种类型的题目:
解题步骤:f(20)=f(10)=f(5)= 5 + 3 = 8,能够看到,当x>=10时,就是本身调用本身,这就是递归,Python代码能够这样写:
In [20]: def func(x): ...: if x < 10: ...: ans = x + 3 ...: print(ans) ...: return ans ...: else: ...: return func(x/2) # 递归调用本身 ...: In [21]: func(20) 8.0 Out[21]: 8.0
函数递归的规则:
必须有一个明确的结束条件
每次进入递归后,运算规模比上一次小(不然无限大,问题没法求解,内存会被占满)
在初始化函数时,能够令函数使用参数,以下:
In [6]: def add(x,y): # 函数拥有参数时,将其写在括号里便可 ...: ''' ...: calculate x plus y ...: ''' ...: return x + y # return语句能够返回计算式
In [7]: add(1,5) # 带参数的调用方法
Out[7]: 6
形参:只是一个名字,不占用真实内存空间
In [6]: def add(x,y): # x,y就是形参,只是一个名称而已,并不占用内存空间 ...: ''' ...: calculate x plus y ...: ''' ...: return x + y
实参:本质是一个变量,占用真实内存空间
In [7]: add(1,5) # 1,5是实参,本质为 在调用函数时,将 x=1,y=5传给add函数,至关于两变量,占用内存资源 Out[7]: 6
按位置参数调用:按形参的位置调用
In [8]: def print_num(a,b,c):
...: '''
...: print num of nums
...: '''
...: print(a)
...: print(b)
...: print(c)
In [9]: print_num(1,3,5)
1
3
5
# 能够看到1和a对应,3和b对应,5和c对应,这就是按位置参数调用
按关键参数调用:调用函数时,直接参数赋值,而不按位置赋值
In [8]: def print_num(a,b,c): ...: ''' ...: print num of nums ...: ''' ...: print(a) ...: print(b) ...: print(c) ...: In [11]: print_num(b=7,a=1,c=10) 1 7 10 # 直接给变量赋值,必须指定是哪一个参数
注意:在调用时,位置参数能够和关键参数混合使用,可是位置参数必定在关键参数以前才行:
In [8]: def print_num(a,b,c): ...: ''' ...: print num of nums ...: ''' ...: print(a) ...: print(b) ...: print(c) ...: In [12]: print_num(5,c=1,b=10) # 混合使用方法 5 10 1 In [13]: print_num(a=4,6,c=10) # 混合使用时,位置参数必需要在关键参数以前,不然报错 File "<ipython-input-13-99c9e145d0a7>", line 1 print_num(a=4,6,c=10) ^ SyntaxError: positional argument follows keyword argument
默认参数:在初始化函数时,能够给形参指定默认值,例如:
In [14]: def print_num(a,b,c=5): # 指定c的默认值为5 ...: print(a) ...: print(b) ...: print(c)
在调用时,若是不须要改变c的值就能够省略不写,若是须要改变其值,调用时从新赋值便可:
In [15]: print_num(1,2) # 使用默认参数 1 2 5 In [17]: print_num(1,2,3) # 按位置参数,令c=3 1 2 3 In [19]: print_num(1,2,c=3) # 按关键参数,令c=3 1 2 3
非固定参数:有时函数在初始化时不肯定要传入参数的数量,这时就要使用非固定参数了
In [22]: def print_num(a,b,c): ...: print(a,b,c) ...: In [23]: print_num(1,2,3,4) # 当参入的参数多于给定的参数时,会抛出异常 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-23-a8e0af192084> in <module> ----> 1 print_num(1,2,3,4) TypeError: print_num() takes 3 positional arguments but 4 were given
*args:将传入的多余参数构形成一个元组
In [26]: def print_num(a,b,c,*args): ...: print(a,b,c) ...: print(args) ...: In [27]: print_num(1,2,3,4,5,6,7,8,9,0) # 多余的参数变成元组保存下来 1 2 3 (4, 5, 6, 7, 8, 9, 0)
**kwargs:将传入的多余参数构形成一个字典
In [28]: def print_num(a,b,c,**kwargs): ...: print(a,b,c) ...: print(kwargs) ...: In [29]: print_num(1,2,3,f=3,g=45,y=123) # 将多余的参数构形成字典保存下来 1 2 3 {'g': 45, 'y': 123, 'f': 3}
最完美的办法:*args和**args一块儿使用
In [30]: def print_num(a,b,c,*args,**kwargs): ...: print(a,b,c) ...: print(args) ...: print(kwargs) ...: In [32]: print_num(1,2,3,4,4,5,f=45,g=23,u=345) 1 2 3 (4, 4, 5) {'g': 23, 'u': 345, 'f': 45}
在Python中,有两种变量:全局变量和局部变量
全局变量:在整个程序中均可以访问的变量,分配在全局数据段,在程序开始运行的时候被加载,生存周期从程序开始到程序结束,也就是说,全局变量被定义在主程序中
局部变量:存在于某个函数或类中,只有在函数或类中才可以被访问,只分配在程序的堆栈中,生存周期从函数开始到函数结束,也就是说,局部变量被定义在子模块中
1 quan_jv_bian_liang = 555 2 3 4 def func(): 5 jv_bu_bian_liang = 666 6 ans = quan_jv_bian_liang + jv_bu_bian_liang 7 print(ans) 8 9 10 print(quan_jv_bian_liang) # 访问全局变量 11 12 print(jv_bu_bian_liang) # 访问局部变量
上面程序的运行结果:
E:\PythonProjects\跟着MS学Python>python -u "e:\PythonProjects\跟着MS学Python\#12\1.py" 555 # 全局变量能正确访问 Traceback (most recent call last): # 局部变量不可以访问 File "e:\PythonProjects\跟着MS学Python\#12\1.py", line 12, in <module> print(jv_bu_bian_liang) NameError: name 'jv_bu_bian_liang' is not defined
继续修改程序,验证全局变量是否能够在函数中被访问:
quan_jv_bian_liang = 555 def func(): jv_bu_bian_liang = 666 ans = quan_jv_bian_liang + jv_bu_bian_liang print(ans) func() # 运行结果 E:\PythonProjects\跟着MS学Python>python -u "e:\PythonProjects\跟着MS学Python\#12\1.py" 1221
# 能够看到全局变量在函数中能够被正确访问
继续修改程序,验证全局变量是否能够在函数内被修改:
quan_jv_bian_liang = 555 def func(): jv_bu_bian_liang = 666 quan_jv_bian_liang = 777 # 修改全局变量的值 ans = quan_jv_bian_liang + jv_bu_bian_liang print(ans) func() print(quan_jv_bian_liang) # 运行结果 E:\PythonProjects\跟着MS学Python>python -u "e:\PythonProjects\跟着MS学Python\#12\1.py" 1443 # 在函数内,全局变量被修改 555 # 在主程序中,全局变量并无被修改
能够看到在函数内并不能真正的修改全局变量,若是非要在函数内修改全局变量,也不是不能够:
quan_jv_bian_liang = 555 def func(): jv_bu_bian_liang = 666 global quan_jv_bian_liang # 申明这是全局变量便可 quan_jv_bian_liang = 777 ans = quan_jv_bian_liang + jv_bu_bian_liang print(ans) func() print(quan_jv_bian_liang) # 运行结果 E:\PythonProjects\跟着MS学Python>python -u "e:\PythonProjects\跟着MS学Python\#12\1.py" 1443 777 # 被正确更改
# 尽可能不要在函数内更改所有变量,这样作可能会致使变量使用混乱,让本身使用变量出错
当函数的参数是函数时,这个函数被称为高阶函数=====( ̄▽ ̄*)b
In [33]: def dunc(x): ...: return x*x ...: In [36]: def add(a,b,f): # 将函数做为参数 ...: print(f(a) + f(b)) In [37]: add(1,2,dunc) 5
针对简单功能的函数,能够不显式的指定函数框架,使用匿名函数即简洁,又能够实现其功能:
In [38]: def func(x): ...: return x*x # 上面的函数使用下面的匿名函数代替: In [39]: func = lambda x:x*x In [40]: func(10) Out[40]: 100
能够看到匿名函数的定义语法:函数名 = lambda 变量 : 函数体
在Python中,有许多内置函数能够直接供咱们使用,以前的讲解其实已经接触不少了,如今来看看所有的内置函数:
具体的使用方法见官方文档:https://docs.python.org/3.5/library/functions.html