Python第四课----函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python第四课----函数相关的知识,希望对你有一定的参考价值。
函数
一、函数
由若干语句组成的语句块,函数名称、参数列表构成,它是组织代码的最小单元。
二、函数的作用
1、对代码的最基本封装,按照功能组织一段代码。 2、目的为了复用,减少冗余代码。
三、函数分类
1、内建函数:max(),reversed()。 2、库函数:math.ceil。
四、def语句定义函数
def 函数名(参数列表) 函数体(代码块) [return 返回值] 函数名就是标识符,命名要求一样。 语句块缩进四个空格。 函数中如果没有return语句,隐式会返回一个None值。 定义中的参数列表是形式参数,只是一种表达,简称形参。
2、调用 函数定义,只是声明,不会执行,需要调用 加上小括号调用 调用时写的参数是实际参数,是传入的值,简称实参
五、函数的定义,调用
def add(x,y): result = x+y return result out = add(4,5) print(out)
函数---->add,计算结果通过返回值返回、返回值可以使用变量接收,函数是可调用对象,callable(add)试一下,是通用的
六、函数参数
1、参数调用时,传入的参数要和定义的个数匹配(可变例外) 2、位置参数:def f(x,y,z) 调用时:f(3,4,5),按照顺序传入实参 3、关键参数:def f(x,y,z) 调用时:f(x=3,y=4,z=5),使用形参名字传入实参的方式,顺序无所谓 4、传参:f(z=None,y=10,x=[1])、f((1,),z=6,x=4.1)、f(y=5,z=6,2)最后这种不行,位置参数必须在关键字参数之前传入
七、参数默认值
1、参数默认值:def f(x=4,y=5):这个时候,x,y都有默认值,默认可以输出 2、参数非常多的时候,并不需要输出所有参数,有默认值就可以了
八、可变参数
1、问题:有多个数,累加求和 def add(nums):----这样的话,nums需要是一个可迭代对象 2、可变位置参数(一个星号)一个形参可以匹配任意个参数x def add(*args):----sum=0,for x in args:----sum+=x 3、可变关键字参数(两个星号) def add(**kwargs): for k,v in kwargs.items( ): print(“{}={}”.format(k,v)) add(x=1,y=2) 只能用关键字调用,组成的是个字典 4、混合使用参数、可变参数: 1、def showconfig(username,password,**kwargs) 2、def showconfig(username,*args,**kwargs) 3、def showconfig(username,password=“mage”,*args,**kwargs) 4、def fn(*args,x,y,**kwargs):---->这么写,调用必须对唯一关键词x、y进行关键字传参 5、fn(*,x,y)强制将x,y变成唯一关键词 6、fn(*agrs,x=5)默认值给了可以直接调用fn()
九:参数解构----实参解构
1、fn(x,y): return(x+y) fn(*(4,5))/*[4,5]/*{4,5}/fn(*range(1,3))/fn((1,2)[0],[3][0]) 2、字典解构fn(**{x:5,y:6})或者fn(*d.keys())或d.valus() 3、def fn(*args): print(args) fn(*[1,2,3]) 4、def fn(*args): sum = 0 for x in args: sum += x print(sum)
十:返回值
十一:作用域
1、一个标识符的可见范围,也就是变量,一般说变量的作用域
2、x = 5 x = 5 def foo(): def foo(): print(x) x+=1 foo() print(x) 可执行,x为全局变量 foo()不可执行,下方的x+=1,实际上是重新定义变量x,但是并不存在
3、全局作用域,global变量,可以管辖下面的函数,但函数内部高度自治,自己管自己局部作用域,local变量,里面可以使用外部的变量,但本地变量,只能在内部使用,外部不可见
4、嵌套结构 def outer( ): def outer( ): o = 65 o = 65 def inner( ): def inner( ): print("inner { }".format(o)) o = 97 print(chr(o)) print("inner { }".format(o)) print("outer { }".format(o)) print(chr(o)) inner( ) print("outer { }".format(o)) outer( ) 打印65,65,A inner( ) 外部变量内部可用,但赋值即定义 outer( )打印结果65,97,a
x = 5 def foo( ): y = x+1 x = 1 print(x) foo( )报错,赋值即定义,上面x用不上,下面的又没有定义就被y拿来使用
5、全局变量global x = 5 def foo(): def foo(): global x global x x = 10 x+=1 x +=1 将x声明为使用外部的全局作用域,外面必须有x的定义 这个x=10,是全局变量,是为外面定义一个变量
6、闭包 自由变量:未在本地作用域定义的变量,例如定义在外层函数作用域的变量 闭包:出现在嵌套函数中,指的是内层函数引用了外层函数的自由变量 def counter(): c = [0] def inc( ): c[0] += 1 return c[0] return inc foo = counter( ) print(foo( ),foo( )) c = 100 print(foo( )) 每次局部变量应该消失,但[ ]是引用对象,每次都会改变,借用的是引用类型
7、nonlocal关键字----关键字绝对不能被占用 使用了nonlocal关键字,将变量标记为在上级的局部作用域中定义,是上级的局部作用域,而不是全局作用域 函数调用为什么会循环count+=1??? def counter(): count = 0 def inc(): nonlocal count count +=1 return count return inc foo = counter( ) print(foo( ),foo( )) 闭包内的函数,在外面foo调用的时候,保留了count这个变量,而且每次都执行了+1
8、函数默认值的作用域:(foo.__defaults__)使用两个下划线+defaults+两个下划线 def foo(xyz=[]): xyz.append(1) print(xyz) print(foo(),id(foo)) print(foo.__defaults__) print(foo(),id(foo)) print(foo.__defaults__) 函数的默认值不会发生变化,缺省值不会改变,是个元组,但元组内的列表发生了改变,这是个引用
def foo(w,u="abc",z=123): u = "xyz" z = 456 print(w,u,z) print(foo.__defaults__) foo("magedu") print(foo.__defaults__) 函数的默认值不会发生改变,重新赋值的展示在函数调用里
9、默认值的作用域用法: def foo(xyz=[],u="abc",z=123): xyz=xyz[:] xyz.append(1) print(xyz) foo() print(foo.__defaults__) foo() print(foo.__defaults__) foo([10]) print(foo.__defaults__) foo([10,5]) print(foo.__defaults__) xyz重新被赋值定义,做了拷贝,原xyz还是不变,默认值始终不变
def foo(xyz=None,u="abc",z=123): if xyz is None: xyz=[] xyz.append(1) print(xyz) foo() print(foo.__defaults__) foo() print(foo.__defaults__) lst = [10] foo(lst) print(lst) print(foo.__defaults__) foo([10,5]) print(foo.__defaults__) 使用不可变类型默认值,如果使用none,则创建新列表,如果,传入一个列表,就修改这个列表,lst发生了变化,但是默认值一直没有发生变化,始终是None,abc,123的元组
def foo(x=None): if x == None: x = [] x.append(1) return x lst = foo() a = foo(lst) print(a) 一般这么写函数,lst=foo()就会执行一次foo(),结果是[1],a=foo(lst)会再执行一次,结果就是[1,1]
十二、函数销毁:
del或重新赋值
十三、树:
1、定义: (1)、非线性解构,每个元素可以有多个前驱和后继(这句话,是前驱0或1,后继多个) (2)、树是n≥0个元素的集合 (3)、n = 0,则是空树,树的根Root没有前驱 (4)、其余元素只能有一个前驱,多个后继 2、递归定义: (1)、有且只有一个特殊元素根,其余元素划分为m个互不相交的集合T1,T2.。。。Tm,每一个集合都是树,称为T的子树Subtree (2)、子树也有自己的根 3、树的概念 (1)、结点,树中的数据元素,每个元素都是一个结点 (2)、结点的度degree:结点拥有的子树的数目,称为度,记作d(v),B的度是1,C的度是2,D的度是3 (3)、叶子结点,结点的度为0,则是叶子结点leaf、终端结点,末端结点 (4)、分支结点,结点度不为0,则是分支结点 ABCDE (5)、分支,结点之间的关系,A和B的分支,关系,这条线 (6)、内部结点,除掉根和叶子结点,中间的结点 (7)、树的度:树内各结点,谁的度数大,树的度数就是多少,上图为3 (8)、孩子(儿子Child)结点,结点的子树的根节点成为成为该结点的孩子 (9)、双亲(父Parent)结点:一个结点是它各个子树的根结点的双亲 (10)、兄弟结点(sibling):具有相同双亲结点的结点 (11)、祖先结点:从根结点到该结点所经分支上所有的结点。ABD都是G的祖先 (12)、子孙结点:结点的所有子树上的结点都成为该结点的子孙,B的子孙是GDHI (13)、结点的层次(Level):根结点为第一层,根的孩子是第二层,以此类推,记作L(v) (14)、树的深度(高度Depth):树的层次的最大值,上图深度为4 (15)、堂兄弟,双亲在同一层的结点 4、树的概念: (1)、有序树:结点的子树是有顺序的,不能交换 (2)、无序树:结点的子树是无序的,可以交换 (3)、路径:树的k个结点n1,n2,。。。nk,满足ni是n(i+1)的双亲,成为n1到nk的一条路径,就是一条线下来的,前一个是后一个的父结点,A-B-D-G (4)、路径长度:路径上结点数-1 (5)、森林:m≥0颗不相交的树的集合 D、E、F,结点的子树集合就是森林 5、树的特点: (1)、唯一的根 (2)、子树不相交 (3)、除了根之外,每个元素只有一个前驱,0或多个后继 (4)、根结点没有前驱,叶子结点没有后继 (5)、如果vi是vj的双亲,则L(vi)=L(vj)-1,双亲比孩子Level小1 (6)、堂兄弟的双亲不一定是兄弟
十四:二叉树
1、每个结点最多两颗子树:二叉树不存在度数大于二的结点 2、二叉树是有序树,左子树,右子树是有顺序的,不能交换 3、即使某个结点只有一棵树,也要确定它是左子树还是右子树 4、二叉树的五种形态 (1)、空二叉树 (2)、只有根结点的二叉树 (3)、根结点只有左子树 (4)、根结点只有右子树 (5)、根结点有左子树和右子树
十五、斜树:
1、左斜树:全是左子树 2、右斜树:全是右子树
十六、满二叉树:
1、一颗二叉树的所有分支结点都存在左子树和右子树,并且叶子结点只存在最下面一层,一个都不能少,左右完全对称 2、同样深度中,满二叉树结点最多 3、k为深度(1≤k≤n),则结点总数为2**k-1
十七:完全二叉树:
1、若二叉树的深度为k,则二叉树的层数从1到k-1层的结点数都达到了最大个数,在第k曾的所有结点都集中在最左边,这就是完全二叉树(最后一层,从左到右,不能空) 2、满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树 3、H在左边,若E有一个分支结点,则不是,必须D有两个,E有一个左子树,才是完全二叉树
十八、二叉树性质:
1、在二叉树的第i层上最多有2**(i-1)个结点 2、深度为k的二叉树,至多有2**k-1个结点 3、对于任意一颗二叉树T,如果其终端结点为n0,度数为2的结点为n2,则有n0=n2+1(叶子结点,是度数为2的结点加1)上图中,叶子结点n0=4(HEFG),n2=3(ABC) 4、叶子结点数-1就等于度数为2的结点数 证明:n0+n1+n2=n(0叶子,1度数为1,2度数为2): n0+n1+n2-1(一棵树的分支数为n-1(总数减去根结点)) 分支数还等于n0*0+n1*1+n2*2-----2n*2+n1 2*n2+n1=n0+n1+n2-1---->n2=n0-1 5、高度为k的二叉树,至少有k个结点(左斜树) 7、具有n个结点的完全二叉树的深度为int((log2n+1))n开方+1取整,或者math.ceil(log2(n+1)) 8、如果有一颗n个结点的完全二叉树,可以按照层序编号 (1)、如果i=1,则结点i是二叉树的根,无双亲,如果i>1,则其双亲是int(i/2),向下取整。就是子结点的编号整除2得到的就是父结点的编号。父节点如果是i,左孩子结点就是2i,右孩子就是2i+1 (2)、如果2i>n,则结点无左孩子,即结点i为叶子结点,否则其左孩子结点存在编号为2i (3)、如果2i+1>n,则结点i无右孩子,否则右孩子存在编号为2i+1
十九、变量名解析原则LEGB
1、Local----先本地作用域,调用结束消亡 2、Enclosing,嵌套函数的闭包的外部函数的命名空间 3、Global----全局,解释器退出时消亡 4、Build-in 内置模块的命名空间,解释器启动到退出,就是生命周期,print、open等
二十、函数执行流程:
1、函数执行流程: 全局帧中生成foo1、2、3、main函数对象 def foo1(b,b1=3): main函数调用 print("foo1 called",b,b1) main中查找内建函数print压栈,将常量字符串压栈,调用函数,弹出栈顶 def foo2(c): main中全局查找函数foo1压栈,将常量100,101压栈,调用foo1函数, foo3(c) 创建栈帧,print压栈,字符串和常量压栈,调用函数,弹出栈顶,返回值。 print("foo3 called",c) 后续全部类似 def foo3(d): print("foo3 called",d) def main(): print("main called") foo1(100,101) foo2(200) print("main called") main()
二十一、递归Recursion
1、函数直接或间接调用自身,就是递归
2、递归需要边界条件
3、当不满足边界条件时,递归前进,当满足边界条件时,递归结束。
本文出自 “13277682” 博客,谢绝转载!
以上是关于Python第四课----函数的主要内容,如果未能解决你的问题,请参考以下文章