python递归函数基础知识_Python基础知识06-函数,递归,内置函数

一、为何使用函数

背景提要:在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下:

whileTrue:if cpu利用率 > 90%:#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接if 硬盘使用空间 > 90%:#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接if 内存占用 > 80%:#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接

改进:把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下:

def发送邮件(内容)#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接whileTrue:if cpu利用率 > 90%:

发送邮件('CPU报警')if 硬盘使用空间 > 90%:

发送邮件('硬盘报警')if 内存占用 > 80%:

发送邮件('内存报警')

对于上述的两种实现方式,第二次必然比第一次的重用性和可读性要好,其实这就是函数式编程和面向过程编程的区别:

函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可

面向对象:对函数进行分类和封装,让开发“更快更好更强...”

二、定义函数的方法

函数是逻辑结构化和过程化的一种编程方法;函数式编程最重要的是增强代码的重用性和可读性。

#python中函数定义方法:

deftest(x):"The function definitions"x+=1

returnx

test(3)#def:定义函数的关键字#test:函数名#():内可定义形参#"":文档描述(非必要,但是强烈建议为你的函数添加描述信息)#x+=1:函数体(泛指代码块或程序处理逻辑)#return:函数体(定义返回值)#调用运行:可以带参数也可以不带#函数名()

1、返回值

函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者,没有返回值的函数也称为过程。

#!/usr/bin/env python#_*_ coding:utf-8 _*_

deftest01():

msg='hello The little green frog'

printmsgdeftest02():

msg='hello WuDaLang'

printmsgreturnmsg

t1=test01()

t2=test02()print 'from test01 return is [%s]' %t1print 'from test02 return is [%s]' %t2#结果

'''hello The little green frog

hello WuDaLang

from test01 return is [None]

from test02 return is [hello WuDaLang]'''

当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None。

2、参数

函数的有三中不同的参数:

1、普通参数:

########## 定义函数 ##########name 叫做函数func的形式参数,简称:形参

deffunc(name):printname########## 执行函数 ##########'wupeiqi' 叫做函数func的实际参数,简称:实参

func('zhangsan')'''1、形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

2、实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

3、位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)'''

2、默认参数:

def func(name, age=18):print "%s:%s" %(name, age)

func('zahngsan', 19) #指定参数

func('lisi') #使用默认参数#注:默认参数需要放在参数列表最后

3、动态参数:传列表、字典

#动态参数一

def func(*args): #将参数包装成列表传入函数

printargs

func(11,33,4,4454,5) #执行方式一

li= [11,2,2,3,3,4,54] #执行方式二

func(*li)#结果

'''(11, 33, 4, 4454, 5)

(11, 2, 2, 3, 3, 4, 54)'''

#动态参数二

def func(**kargs): #将参数包装成字典传入函数

printkargs

func(name= 'zhangsan', age = 18) #执行方式一

li = {'name':'zhangsan', 'age':18, 'gender':'male'} #执行方式二,字典必须先定义好

func(**li)#结果

'''{'age': 18, 'name': 'zhangsan'}

{'gender': 'male', 'age': 18, 'name': 'zhangsan'}'''

#动态参数三

def func(*args, **kwargs):printargsprint kwargs

importsmtplibfrom email.mime.text importMIMETextfrom email.utils importformataddr

msg= MIMEText('邮件内容', 'plain', 'utf-8')

msg['From'] = formataddr(["武沛齐",'wptawy@126.com'])

msg['To'] = formataddr(["走人",'424662508@qq.com'])

msg['Subject'] = "主题"server= smtplib.SMTP("smtp.126.com", 25)

server.login("wptawy@126.com", "邮箱密码")

server.sendmail('wptawy@126.com', ['424662508@qq.com',], msg.as_string())

server.quit()

发送邮件实例

三、函数是第一类对象

在python中所有的名字都没有储值功能,函数是第一个对象。

deffoo():print("yyp")

foo()#输出结果:

yyp

可以当做参数

deffoo():print "tom"

deffunc(msg):printmsg

msg()

func(foo)#输出结果:

tom

可以当做返回值

deffoo():print "tom"

deffunc(msg):returnmsg

f=func(foo)printf

f()#输出结果:##tom

可以当做容器类型的一个元素

deffoo():return "tom"func_dic={'foo':foo()}print func_dic.get('foo')#输出结果:#tom

一类对象指的是:函数可以被当做数据来处理被引用

四、局部变量和全局变量

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

当全局变量与局部变量同名时:在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

name='lhf' #全局变量

defchange_name():print('我的名字',name)

change_name()defchange_name():

name='帅了一笔' #局部变量

print('我的名字',name)

change_name()print(name)defchange_name():globalname

name='帅了一笔'

print('我的名字',name)

change_name()print(name)

五、前向引用之-函数即变量

defaction():print 'in the action'logger()

action()#报错NameError: global name 'logger' is not defined

deflogger():print 'in the logger'

defaction():print 'in the action'logger()

action()

六、嵌套函数和作用域

name = "yyp"

defchange_name():

name= "yyp2"

defchange_name2():

name= "yyp3"

print("第3层打印",name)

change_name2()#调用内层函数

print("第2层打印",name)

change_name()print("最外层打印",name)

作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变,此时,在最外层调用change_name2()会出错。

#例一:

name='yyp'

deffoo():

name='sy'

defbar():print(name)returnbar

func=foo()

func()

例二:

name='yyp'

deffoo():

name='sy'

defbar():

name='tom'

deftt():print(name)returnttreturnbar

func=foo()

func()()

七、递归调用

递归特性:

必须有一个明确的结束条件

每次进入更深一层递归时,问题规模相比上次递归都应有所减少

递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

defcalc(n):print(n)if int(n/2) ==0:returnnreturn calc(int(n/2))

calc(10)#输出:#10#5#2

#!/usr/bin/env python#_*_ coding:utf-8 _*_

importtime

person_list=['alex','wupeiqi','yuanhao','linhaifeng']defask_way(person_list):print('-'*60)if len(person_list) ==0:return '没人知道'person=person_list.pop(0)if person == 'linhaifeng':return '%s说:我知道,老男孩就在沙河汇德商厦,下地铁就是' %personprint('hi 美男[%s],敢问路在何方' %person)print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' %(person,person_list))

time.sleep(3)

res=ask_way(person_list)#print('%s问的结果是: %res' %(person,res))

returnres

res=ask_way(person_list)print(res)

递归问路

data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]defbinary_search(dataset, find_num):print(dataset)if len(dataset) > 1:

mid= int(len(dataset) / 2)if dataset[mid] == find_num: #find it

print("找到数字", dataset[mid])elif dataset[mid] > find_num: #找的数在mid左面

print("\033[31;1m找的数在mid[%s]左面\033[0m" %dataset[mid])returnbinary_search(dataset[0:mid], find_num)else: #找的数在mid右面

print("\033[32;1m找的数在mid[%s]右面\033[0m" %dataset[mid])return binary_search(dataset[mid + 1:], find_num)else:if dataset[0] == find_num: #find it

print("找到数字啦", dataset[0])else:print("没的分了,要找的数字[%s]不在列表里" %find_num)

binary_search(data,66)

二分查找

八、冒泡算法

需求:请按照从小到大对列表 [13, 22, 6, 99, 11] 进行排序

思路:相邻两个值进行比较,将较大的值放在右侧,依次比较!

#第一步

li = [13, 22, 6, 99, 11]for m in range(4): #等价于 #for m in range(len(li)-1):

if li[m]> li[m+1]:

temp= li[m+1]

li[m+1] =li[m]

li[m]=temp#第二步

li = [13, 22, 6, 99, 11]for m in range(4): #等价于 #for m in range(len(li)-1):

if li[m]> li[m+1]:

temp= li[m+1]

li[m+1] =li[m]

li[m]=tempfor m in range(3): #等价于 #for m in range(len(li)-2):

if li[m]> li[m+1]:

temp= li[m+1]

li[m+1] =li[m]

li[m]=tempfor m in range(2): #等价于 #for m in range(len(li)-3):

if li[m]> li[m+1]:

temp= li[m+1]

li[m+1] =li[m]

li[m]=tempfor m in range(1): #等价于 #for m in range(len(li)-4):

if li[m]> li[m+1]:

temp= li[m+1]

li[m+1] =li[m]

li[m]=tempprintli#第三步

li = [13, 22, 6, 99, 11]for i in range(1,5):for m in range(len(li)-i):if li[m] > li[m+1]:

temp= li[m+1]

li[m+1] =li[m]

li[m]= temp

冒泡算法

九、匿名函数

匿名函数就是不需要显式的指定函数

defcalc(n):return n**nprint(calc(10))#换成匿名函数

calc = lambda n:n**nprint(calc(10))

匿名函数主要是和其它函数搭配使用的呢,如下

l=[3,2,100,999,213,1111,31121,333]print(max(l))

dic={'k1':10,'k2':100,'k3':30}print(max(dic))print(dic[max(dic,key=lambdak:dic[k])])

res= map(lambda x:x**2,[1,5,7,4,8])for i inres:print(i)#输出#1#25#49#16#64

十、函数式编程

高阶函数:满足俩个特性任意一个即为高阶函数

函数的传入参数是一个函数名

函数的返回值是一个函数名

#普通条件语句

if 1 == 1:

name= 'zhangsan'

else:

name= 'lisi'

#三元运算

name = 'zhangsan' if 1 == 1 else 'lisi'

三元运算

####################### 普通函数 #######################定义函数(普通方式)

deffunc(arg):return arg + 1

#执行函数

result = func(123)####################### lambda #######################定义函数(lambda表达式)

my_lambda = lambda arg: arg + 1

#执行函数

result = my_lambda(123)

lambda表达式

map

遍历序列,对序列中每个元素进行操作,最终获取新的序列。

li = [11, 22, 33]

new_list= map(lambda a: a + 100, li)

每个元素增加100

li = [11, 22, 33]

sl= [1, 2, 3]

new_list= map(lambda a, b: a + b, li, sl)

两个列表对应元素相加

array=[1,3,4,71,2]

ret=[]for i inarray:

ret.append(i**2)print(ret)#如果我们有一万个列表,那么你只能把上面的逻辑定义成函数

defmap_test(array):

ret=[]for i inarray:

ret.append(i**2)returnretprint(map_test(array))#如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样

defadd_num(x):return x+1

defmap_test(func,array):

ret=[]for i inarray:

ret.append(func(i))returnretprint(map_test(add_num,array))#可以使用匿名函数

print(map_test(lambda x:x-1,array))#上面就是map函数的功能,map得到的结果是可迭代对象

print(map(lambda x:x-1,range(5)))

map函数

filter

对于序列中的元素进行筛选,最终获取符合条件的序列

#filter第一个参数为空,将获取原来序列

li = [11, 22, 33]

new_list= filter(lambda arg: arg > 22, li)

获取列表中大于12的所有元素集合

#!/usr/bin/env python#_*_ coding:utf-8 _*_

#电影院聚集了一群看电影bb的傻逼,让我们找出他们

movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao']deftell_sb(x):return x.startswith('sb')deffilter_test(func,array):

ret=[]for i inarray:iffunc(i):

ret.append(i)returnretprint(filter_test(tell_sb,movie_people))#函数filter,返回可迭代对象

print(filter(lambda x:x.startswith('sb'),movie_people))

filter函数

reduce

对于序列内所有元素进行累计操作

#reduce的第一个参数,函数必须要有两个参数#reduce的第二个参数,要循环的序列#reduce的第三个参数,初始值

li= [11, 22, 33]

result= reduce(lambda arg1, arg2: arg1 + arg2, li)

获取序列所有元素的和

#!/usr/bin/env python#_*_ coding:utf-8 _*_

from functools importreduce#合并,得一个合并的结果

array_test=[1,2,3,4,5,6,7]

array=range(100)#报错啊,res没有指定初始值

defreduce_test(func,array):

l=list(array)for i inl:

res=func(res,i)returnres#print(reduce_test(lambda x,y:x+y,array))

#可以从列表左边弹出第一个值

defreduce_test(func,array):

l=list(array)

res=l.pop(0)for i inl:

res=func(res,i)returnresprint(reduce_test(lambda x,y:x+y,array))#我们应该支持用户自己传入初始值

def reduce_test(func,array,init=None):

l=list(array)if init isNone:

res=l.pop(0)else:

res=initfor i inl:

res=func(res,i)returnresprint(reduce_test(lambda x,y:x+y,array))print(reduce_test(lambda x,y:x+y,array,50))

reduce函数

map,filter,reduce小结

#!/usr/bin/env python#_*_ coding:utf-8 _*_

#当然了,map,filter,reduce,可以处理所有数据类型

name_dic=[

{'name':'alex','age':1000},

{'name':'wupeiqi','age':10000},

{'name':'yuanhao','age':9000},

{'name':'linhaifeng','age':18},

]#利用filter过滤掉千年王八,万年龟,还有一个九千岁

deffunc(x):

age_list=[1000,10000,9000]return x['age'] not inage_list

res=filter(func,name_dic)for i inres:print(i)

res=filter(lambda x:x['age'] == 18,name_dic)for i inres:print(i)#reduce用来计算1到100的和

from functools importreduceprint(reduce(lambda x,y:x+y,range(100),100))print(reduce(lambda x,y:x+y,range(1,101)))#用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sb

name=['alex','wupeiqi','yuanhao']

res=map(lambda x:x+'_sb',name)for i inres:print(i)

总结

十一、内置函数

#!/usr/bin/env python#_*_ coding:utf-8 _*_

字典的运算:最小值,最大值,排序

salaries={'egon':3000,'alex':100000000,'wupeiqi':10000,'yuanhao':2000}

迭代字典,取得是key,因而比较的是key的最大和最小值>>>max(salaries)'yuanhao'

>>>min(salaries)'alex'可以取values,来比较>>>max(salaries.values())>>>min(salaries.values())

但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键>>> max(salaries,key=lambdak:salary[k])'alex'

>>> min(salaries,key=lambdak:salary[k])'yuanhao'也可以通过zip的方式实现

salaries_and_names=zip(salaries.values(),salaries.keys())

先比较值,值相同则比较键>>>max(salaries_and_names)

(100000000, 'alex')

View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值