函数
1.函数的定义:
def 函数名(参数):
#解释函数的功能
代码块
返回值
函数的定义主要有如下要点:
- def:表示函数的关键字
- 函数名:函数的名称,日后根据函数名调用函数
- 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
- 参数:为函数体提供数据,可不传参数,若不传参数则调用函数时不能传参数
- 返回值:当函数执行完毕后,可以给调用者返回数据。若没有返回值,则返回None
- 遇到第一个return则函数结束
返回值=0:返回None
返回值=1:返回对象object
返回值>1:返回元组tuple
def test(x): ''' 这个函数是用来计算y=2x+4的值 :param:整形的数字 返回值:y ''' y=2*x+4 print(y) return y print(test) test(3)
2.函数的参数
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传给形参。因此应预先用赋值,输入等办法使参数获得确定值。
def calc(x,y): res=x**y return res a=10 b=2 print(calc(a,b))
3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
def test(x,y,z): print(x) print(y) print(z) test(1,2,3) test(y=4,x=3,z=2)#关键字参数
#若混合使用,位置参数必须在关键字参数的左边
4.默认参数
def handle(x,type='rers'): print(x) print(type) handle('hello') handle('hello','world') >>>hello rers >>>hello world
5.参数组
#参数组:**字典 *列表:接收参数时以列表形式接收,处理时以元组方式处理 def test(x,*args): print(x) print(args) test(1,2,3,[6],{123:'er'}) test(1,['x','y','z'])#以整体形式传给*args元组的第一个元素 test(1,*['x','y','z'])#以列表形式传给*args,相当于遍历列表中元素赋值给args test(1,*{'name':'zlex'})#相当于遍历字典的key传给元组 >>>1 (2, 3, [6], {123: 'er'}) >>>1 (['x', 'y', 'z'],) >>>1 ('x', 'y', 'z') >>>1 ('name',)
def test(x,**kwargs): print(x) print(kwargs) test(1,y=3,z=4,k=5)#后面的值以字典的形式传给**kwargs >>>1 {'y': 3, 'z': 4, 'k': 5}
def test(x,*args,**kwargs): print(x) print(args) print(kwargs) test(1,3,4,5,6,z=4,k=5) >>>1 (3, 4, 5, 6) {'z': 4, 'k': 5} ########################## test(1,[3,4,5,6],{'z':4,'k':5},z=4,k=5) >>>1 ([3, 4, 5, 6], {'z': 4, 'k': 5}) {'z': 4, 'k': 5} ################## test(1,*[3,4,5,6],**{'z':4,'k':5}) >>>1 (3, 4, 5, 6) {'z': 4, 'k': 5}
默认多余的位置参数传给*args,多余的关键字参数传给**kwargs
局部变量与全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
name='alex' def change(): print(name) change() print(name)
global关键字:
#如果函数无global关键字: #——有声明局部变量 name=['aaa','bbb'] def change1(): name='ccc' print(name) change1() >>>ccc #——无声明局部变量 name=['aaa','bbb'] def change2(): print(name) change2() >>>[aaa,bbb] ####################### #如果函数中有global关键字: #——有声明局部变量 name=['aaa','bbb'] def change3(): global name name='ddd' print(name) change3() >>>ddd #——无声明局部变量 name=['aaa','bbb'] def change4(): global name name.append('eee') print(name) >>>[aaa,bbb,eee]
书写规范:全局变量一般都大写,局部变量一般都小写
练习:
NAME='海风' def huangwei(): name='黄伟' print(name) def liuyang(): name='刘洋' print(name) def huzhihua(): name='沪指花' print(name) print(name) huzhihua() liuyang() print(name) huangwei() >>>黄伟 刘洋 刘洋 沪指花 黄伟
name="刚亮" def weihou(): name="陈卓" def weiweihou(): global name name="冷静" weiweihou() print(name) print(name) weihou() print(name) >>>刚亮 陈卓 冷静
nonlocal关键字:指定上一级变量
name="刚亮" def weihou(): name="陈卓" def weiweihou(): nonlocal name name="冷静" weiweihou() print(name) print(name) weihou() print(name) >>>刚亮 冷静 刚亮
风湿理论:函数即变量,函数在定义时相当于开辟一部分内存将函数内容存入,但不执行,调用函数名时再执行函数中内容。
递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
def cal(n): print(n) if int(n/2)==0: return n return cal(int(n/2)) cal(10) >>>10 5 2 1
递归特性:
1.必须有一个明确的结束条件
2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会多加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,就会导致栈的溢出)
#0,1,1,2,3,5,8,13 # #斐波那契数列 a=0 b=1 def phil(): global b global a print(a) c=a+b a=b b=c if c>100000: return c return phil() phil() >>>0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
问路函数
#问路函数,问第一个人不知道,第一个人就问第二个人,依次类推 #问到答案时依次返回答案 person_list=['luren1','luren2','luren3','luren4'] def ask_way(p_l): print('#'*60) if len(p_l)==0: return '我们都不知道' p=p_l.pop(0) if p=='luren4': return '%s说:我知道,在五环大道'%p # time.sleep(1) print('hi%s,请问家乐福怎么走'%p) print('%s说:我不知道,我帮你问问%s'%(p,",".join(p_l))) res=ask_way(p_l) print('%s问的结果是:%s'%(p,res)) return res result=ask_way(person_list) print(result) >>>############################################################ hiluren1,请问家乐福怎么走 luren1说:我不知道,我帮你问问luren2,luren3,luren4 ############################################################ hiluren2,请问家乐福怎么走 luren2说:我不知道,我帮你问问luren3,luren4 ############################################################ hiluren3,请问家乐福怎么走 luren3说:我不知道,我帮你问问luren4 ############################################################ luren3问的结果是:luren4说:我知道,在五环大道 luren2问的结果是:luren4说:我知道,在五环大道 luren1问的结果是:luren4说:我知道,在五环大道 luren4说:我知道,在五环大道