一、函数的基本语法和特性
函数的定义
函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的。函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。
python中函数的分类
- 内置函数
- 自定义函数
特性:
- 减少重复代码
- 使程序有更好的扩展性
- 让程序更容易维护
定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
函数的语法
1 #函数 2 def fun1(a,b): #a,b 是指形参 3 ‘‘‘fun1‘‘‘ 4 print(‘in the fun1‘) 5 return 0 6 7 #注意函数是有返回值的 8 #过程 9 def fun2(): 10 ‘‘‘fun2‘‘‘ 11 print(‘in the fun2‘) 12 #没有返回值的函数我们一般让我是函数的过程 13 #函数式编程就是这种模式
二、函数的参数
参数:
首先说明,在python中,函数定义好后是存放在内存里面的,类似我们通常所说的变量。而形参没有任何实际意义,只有在被调用的时候才会分配内存单元,而函数调用结束后则会被释放;而实参可以是常量,变量、表达式、函数等,实参被调用时必须得有确定的值,这样才可以把这些值传给形参。
参数的分类:形参,默认参数,不定长参数,关键字参数
默认参数:即有些情况下,一些参数必须提供,默认的情况下是一个固定的值,只有在少数情况下会修改,这种情况可以选择默认参数。
不定长参数:在定义函数时,不确定用户需要传入多少个参数,这时使用不定长参数。
关键字参数:一般情况下,传入参数必须按照给定的参数顺序传入,若不一定知道参数的顺序,可以使用关键字参数来传入。
注意:在传入参数的时候位置参数必须在关键字参数的前面。
1 ##参数形式 2 #1不传参 3 def fun1(): 4 print(‘不能传参数‘) 5 6 7 #2必备参数 8 def fun2(a): 9 print(‘必须传参数:‘,a) 10 11 12 #3默认参数 13 def fun3(b=2): 14 print(‘默认参数:‘,b) #可传可不传 15 #可选参数 16 def fun4(*arg): 17 print(‘可传0个到多个:‘,arg)#可传0个到多个 包装成元组 18 #fun4(*[1,2]) 加个* ,就把里面的壳去掉(解包) 19 20 21 22 #关键字参数 23 #定义的时候是跟必备参数一样的 24 #必须放到最后 25 26 def fun6(**kwarg): 27 print(‘关键字参数‘,kwarg)# 可传0个到多个 包装成字典 28 #fun6(a=1,b=2) 遵循变量命名规则 29 #fun6(**{‘a‘:1}) 必须是字符串 30 31 32 ##参数混合的时候 关键字参数放最后 根据定义的顺序 确保必备参数只能拿到值,并且只能一个 33 #必备参数+默认参数 34 def fun7(a,b=1): #默认参数必须在必备参数的后面 35 print(a,b) 36 37 def fun8(b,m=1,*a): 38 print(b) 39 print(m) 40 print(a) 41 42 def fun8(*a,b,m): #尽量不用这种方式,这种方式需要用关键字的方式传入参数 43 print(a,b,m) 44 print(b) 45 46 def fun9(*a,b,m=1): 47 print(a,b,m) 48 print(b)
一般情况下按照以下形式传入参数:这样更容易理解程序。
1 def fun1(x,y=2): 2 print(x) 3 print(y) 4 5 # fun1(1) #默认参数,在调用函数的时候可以不传参 6 # fun1(1,3) #也可以选择传参 7 8 def fun2(*args): #不定长参数,当不确定参数的长度时用不定长参数 9 print(args) 10 11 # fun2(1,3,4,5,‘d‘) 12 13 def fun3(**kwargs):#关键字参数,接受N个关键字参数,并把它们转换为字典 14 print(kwargs) 15 16 fun3(i = ‘lll‘) 17 18 def fun4(a,b = 1,*args,**kwargs): 19 print(a) 20 print(b) 21 print(args) 22 print(kwargs) 23 fun4(1,2,3,3,3,x = ‘lll‘) #传参的时候关键字参数必须在位置参数后面
变量:
在函数中,变量分为全局变量和局部变量。
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
1 school = ‘oleboy‘ #全局变量 2 3 def charge_school(): 4 school = ‘TANZHOU‘ #在函数里面是一个局部变量 5 print(school) 6 # charge_school() 7 # print(school) 8 #上面可以看出,在调用函数后,函数外部并没有改变school的值 9 10 def charge_school2(): 11 global school 12 school = ‘TANZHOU‘ 13 print(school) 14 charge_school2() 15 print(school) 16 #重上面看出,当申明global之后,函数内的变量成为了全局变量,在函数 17 #内也可以进行访问并修改,在日常工作中做好不要这么做 18 19 20 names = [‘Alex‘,‘Jack‘,‘Wallace‘] 21 name_tuple= (1,2,3,4) 22 23 def charge_name(): 24 names[1]=‘金角大王‘ 25 print(names) 26 charge_name() 27 print(names) 28 29 ‘‘‘从上可看出,当函数内的变量和全局变量为可变对象时,在函数内可以对其进行修改 30 ‘‘‘ 31 a = 1 #全局变量 32 33 def fun(): 34 global a 35 a = 2 #局部变量,正常情况下无法修改全局变量,若要修改用global 最好不要这么做 36 print(a) 37 38 print(a) 39 b = fun() 40 print(a)
虽然在实例上,通过global可以将一个局部变量声明为全局变量,但是这种方式对于代码的可维护上非常不好,尽量避免这种操作。
三、返回值
函数的返回值可以是大多数的数据类型,也可以是变量名,函数名也可以是函数本身:
1 def text1(): 2 print(‘in the text1‘) 3 return 0,{0,1},[0,1,3] 4 5 def text2(): 6 return text1 返回的是函数 7 8 y = text2()() #可以进行调用
四、嵌套函数
嵌套函数指的是,函数内定义另一个函数例:
1 def fun1(): 2 print("fun1") 3 def fun2(): 4 print("fun2") 5 fun2() 6 >>a = fun1() 7 fun1 #先调用fun1,在fun1里面调用fun2 8 fun2
嵌套函数的具体用法将会在后面的学习中提到。
五、递归
递归函数是指函数内部调用自己,这样的函数就是递归函数。
1 def fun1(n): 2 if n == 1: 3 return 1 #递归的结束条件 4 else: 5 return fun1(n-1)+1 6 >>print(fun1(3)) 7 3
递归的必备条件:
- 必须有一个明确的结束条件
- 每次进入更深层递归时,问题的规模相比上次递归都应有所减少
递归的局限性:
递归的效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一次函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。有用栈的大小不是无限的,所以递归掉用的次数过多,就会导致栈溢出)
递归的应用,二分法查找:
1 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] 2 3 def binary_search(dataset,find_num): 4 print(dataset) 5 6 if len(dataset) >1: 7 mid = int(len(dataset)/2) 8 if dataset[mid] == find_num: #find it 9 print("找到数字",dataset[mid]) 10 elif dataset[mid] > find_num :# 找的数在mid左面 11 print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid]) 12 return binary_search(dataset[0:mid], find_num) #再次调用原函数 13 else:# 找的数在mid右面 14 print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid]) 15 return binary_search(dataset[mid+1:],find_num) 16 else: 17 if dataset[0] == find_num: #find it 18 print("找到数字啦",dataset[0]) 19 else: 20 print("没的分了,要找的数字[%s]不在列表里" % find_num) 21 22 >>binary_search(data,66) 23 [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] 24 找的数在mid[18]右面 25 [20, 21, 22, 23, 30, 32, 33, 35] 26 找的数在mid[30]右面 27 [32, 33, 35] 28 找的数在mid[33]右面 29 [35] 30 没的分了,要找的数字[66]不在列表里
六、匿名函数
匿名函数没有函数名,一般情况就是只调用一次,后续不会再调用。
1 cala = lambda n:n*n #一般用于只调用一次 2 ‘‘‘ 3 相当于 4 def fun1(n): 5 return n*n 6 ‘‘‘ 7 print(cala(10))
七、高阶函数
高阶函数指的是将函数名作为参数传入。
1 def high_fun(a,b,f): 2 return f(a)+f(b) 3 4 >>a = high_fun(1,-2,abs) #abs()求一个函数的绝对值 5 3
上面例子中,参数f可以任意的函数名。
八、内置函数
注:内置函数将会作为另一章进行详细的讲解。
原文地址:https://www.cnblogs.com/wallacewang/p/8850328.html