标签:可变 dep tuple 构建 cal 实现 limit 深度 可变参数
函数def语句定义函数
def 函数名(参数列表):
函数体(代码块)
[return 返回值]
函数名就是标识符,命名要求一样语句块必须缩进,约定4个空格Python的函数没有return语句,隐式会返回一个None值定义中的参数列表成为形式参数,只是一种符号表达,简称形参
调用
函数定义,只是声明了一个函数,它不会被执行,需要调用调用的方式,就是函数名加上小括号,括号内写上参数调用时写的参数是实际参数,是实实在在传入的值,简称实参
参数调用时传入的参数要和定义的个数相匹配(可变参数例外)
位置参数
def f(x, y, z) 调用使用 f(1, 3, 5)按照参数定义顺序传入实参
关键字参数
def f(x, y, z) 调用使用 f(x=1, y=3, z=5),使用形参的名字来出入实参的方式,如果使用了形参名字,那么传参顺序就可和定义顺序不同
传参
f(z=None, y=10, x=[1])
f((1,), z=6, y=4.1)
f(y=5, z=6, 2) #
要求位置参数必须在关键字参数之前传入,位置参数是按位置对应的
参数默认值(缺省值)
定义时,在形参后跟上一个值
def add(x=4, y=5):
return x+y
测试调用 add(6, 10) 、add(6, y=7) 、add(x=5) 、add()、add(y=7)、 add(x=5, 6) 、add(y=8,
4)、add(x=5, y=6)、add(y=5, x=6)
测试定义后面这样的函数 def add(x=4,y)
作用
参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值
参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用
举例
定义一个函数login,参数名称为host、port、username、password
可变参数
一个形参可以匹配任意个参数
位置参数的可变参数
有多个数,需要累加求和
在形参前使用*表示该形参是可变参数,可以接收多个实参
收集多个实参为一个tuple
关键字参数的可变参数
形参前使用*符号,表示可以接收多个关
可变参数混合使用
总结
有位置可变参数和关键字可变参数
位置可变参数在形参前使用一个星号
关键字可变参数在形参前使用两个星号**
位置可变参数和关键字可变参数都可以收集若干个实参,位置可变参数收集形成一个tuple,关
键字可变参数收集形成一个dict
混合使用参数的时候,可变参数要放到参数列表的最后,普通参数需要放到参数列表前面,位
置可变参数需要在关键字可变参数之前
keyword-only参数(Python3加入)
如果在一个星号参数后,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通的
参数了,而是keyword-only参数
编写一个函数,接受一个参数n,n为正整数,左右两种打印方式。要求数字必须对齐
函数的返回值
Python函数使用return语句返回“返回值”
所有函数都有返回值,如果没有return语句,隐式调用return None
return 语句并不一定是函数的语句块的最后一条语句
一个函数可以存在多个return语句,但是只有一条可以被执行。如果没有一条return语句被执
行到,隐式调用return None
如果有必要,可以显示调用return None,可以简写为return
如果函数执行了return语句,函数就会返回,当前被执行的return语句之后的其它语句就不会
被执行了
作用:结束函数调用、返回值
函数嵌套
函数嵌套
在一个函数中定义了另外一个函数
函数有可见范围,这就是作用域的概念
内部函数不能在外部直接使用,会抛NameError异常,因为它不可见
作用域***
作用域
一个标识符的可见范围,这就是标识符的作用域。一般常说的是变量的作用域
全局作用域
在整个程序运行环境中都可见
局部作用域
在函数、类等内部可见
局部变量使用范围不能超过其所在的局部作用域
从嵌套结构例子看出
外层变量作用域在内层作用域可见
全局变量global,使用global关键字的变量
global使用原则
外部作用域变量会内部作用域可见,但也不要在这个内部的局部作用域中直接使用,因为
函数的目的就是为了封装,尽量与外界隔离
如果函数需要使用外部全局变量,请使用函数的形参传参解决
自由变量:未在本地作用域中定义的变量。例如定义在内存函数外的外层函数的作用域中的变量
闭包:就是一个概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成
了闭包。
使用了nonlocal关键字,将变量标记为不在本地作用域定义,而在上级的某一级局部作用域中定义,但不
能是全局作用域中定义
变量名解析原则LEGB
Local,本地作用域、局部作用域的local命名空间。函数调用时创
建,调用结束消亡
Enclosing,Python2.2时引入了嵌套函数,实现了闭包,这个就
是嵌套函数的外部函数的命名空间
Global,全局作用域,即一个模块的命名空间。模块被import时
创建,解释器退出时消亡
Build-in,内置模块的命名空间,生命周期从python解释器启动
时创建到解释器退出时消亡。例如 print(open),print和open都
是内置的变量
所以一个名词的查找顺序就是LEGB
插入排序
直接插入排序原理
在未排序序列中,构建一个子排序序列,直至全部数据排序完成
将待排序的数,插入到已经排序的序列中合适的位置
增加一个哨兵,放入待比较值,让它和后面已经排好序的序列比较,找到合适的插入点
匿名函数
匿名,即没有名字
匿名函数,即没有名字的函数
没有名字如何定义
没有名字如何调用
如果能调用,如何使用
匿名函数
使用lambda关键字来定义匿名函数
参数列表不需要小括号
冒号是用来分割参数列表和表达式的
不需要使用return,表达式的值,就是匿名函数返回值
lambda表达式(匿名函数)只能写在一行上,被称为单行函数
用途
在高阶函数传参时,使用lambda表达式,往往能简化代码
递归Recursion
递归要求
递归一定要有退出条件,递归调用一定要执行到这个退出条件。没有退出条件的递归调用,就是无限
调用
递归调用的深度不宜过深
Python对递归调用的深度做了限制,以保护解释器
超过递归深度限制,抛出RecursionError: maxinum recursion depth exceeded 超出最大深
度
sys.getrecursionlimit()
递归的性能
循环稍微复杂一些,但是只要不是死循环,可以多次迭代直至算出结果
fib函数代码极简易懂,但是只能获取到最外层的函数调用,内部递归结果都是中间结果。而且给定一个n
都要进行近2n次递归,深度越深,效率越低。为了获取斐波那契数列需要外面在套一个n次的循环,效率
就更低了
递归还有深度限制,如果递归复杂,函数反复压栈,栈内存很快就溢出了
递归总结
递归是一种很自然的表达,符合逻辑思维
递归相对运行效率低,每一次调用函数都要开辟栈帧
递归有深度限制,如果递归层次太深,函数反复压栈,栈内存很快就溢出了
如果是有限次数的递归,可以使用递归调用,或者使用循环代替,循环代码稍微复杂一些,但是只要不是
死循环,可以多次迭代直至算出结果
绝大多数递归,都可以使用循环实现
即使递归代码很简洁,但是能不用则不用递归
标签:可变 dep tuple 构建 cal 实现 limit 深度 可变参数
原文地址:http://blog.51cto.com/13896223/2164849