python-- 函数
*******求字符串的长度*********
g = 'hello world'
1, print(len(g))
2,#for 循环求字符串的长度 length = 0 for i in g: length+= 1 print(length)
函数(封装程序)
*****为什么要用函数:提高代码的可读性,避免代码重复,提高代码的复用性。
一、初识函数的定义与调用
def mylen(): #def 关键字加函数名(): #函数体 s = 'hello world' a = 0 for i in s: a+=1 print(a) mylen() #函数的调用,必须是函数名加括号
函数的定义:1,函数及工具,我们把事先准备工具的过程可以当做定义一个函数,拿来用准备好的工具叫做函数的调用。
2,def 关键字开头,空格后函数名加括号冒号
3,函数名命名规范:函数名只能包含函字符串,下划线和数字不能以数字开头,不能使python的关键字。简短,可描述性,且能表达函数功能。
4,函数应有注释对功能和参数进行说明,写在函数下的第一行,增强函数代码的可读性。
函数的作用:节省空间,重复调用代码。
函数的调用:函数名加括号。
写一个函数;关键字+函数名--------子代码-----优先写注释-------再写函数体
结论:函数必须是先定义后调用的。
******pass在python程序中的作用:表示空的语句块。用来占位,也可是标记,常用与符合语句中编写空的主体。(写代码没有思路写不出来时可以用paas占位,标记,程序不会报错。)
*****
1、定义一个函数
def func(): print('hello word') func()
2、函数的分类
内置函数:无须定义,python解释器都弄好了
如
print(len('hfgsgj00')) #求长度 print(max([1,2,3,4])) #最大值 print(min([54,778,65,7865])) #最小值 print(sum([12,4864,5])) #求和
自定义函数:
def mylen():
pass
3、返回值
def mylen(): #定义函数 d = 'hello world' length = 0 for i in d: length+= 1 return length #返回length值 str = mylen() #调用函数 print(str)
返回值:return(返回)后的那个数就叫返回值,结束程序执行
return与函数而言有三种形式的返回
1,没有返回值------就是不写return的情况下,函数默认返回None,只写return后没有返回值函数也默认返回None
#没有return默认返回None def func(): a = 1 print(a) c = func() print(c)
#只有return返回None def func(): a = 1 print(a) return c = func() print(c)
2,只返回一个值--------后跟一个返回值,可以跟任意类型的值
#返回一个值 def ret_demo(): print(1111) return None #return 后跟None返回None ret = ret_demo() print(ret)
#返回一个值 def mylen(): s = 'hello world' length = 0 for i in s: length+=1 return length a = mylen() print(a)
3,返回多个值-------return后可以跟多个任意类型的返回值,返回的值是以元组类型
注;如果在函数中有多个return,当函数执行时只执行第一个return,执行完第一个return函数结束执行
#return 返回多个值 def func(): '.....' return 1,23,3,5,40 a = func() print(a)
#return 返回多个值 def func(): '.......' return ['a',1],10,{'k':'v'},'gdsf' #return可返回任意类型数据,以元组的形式打印 s,b,a,c= func() #可用多个值接收 print(s)
def my_len(str): count = 0 for i in str: count+=1 if len(str) > 2: return True else: return False str = 'df' print(my_len(str))
二、参数(实参,形参)
#传递多个参数 def mymax(x,y): #x,y是形参 a_max = x if x > y else y return a_max ma = mymax(10,20) #10,20是实参 print(ma)
1,形参:形式参数,在函数定义时接受的值
形参:默认参数,动态参数,位置参数
参数种类与定义;
1、默认参数:设置默认值(将变化小的值设定为默认参数)
#默认参数的定义 def stu_info(sex,name): return name,sex print(stu_info('马德胜','男'))
2、位置参数:按位置顺序一一对应传参(必须传值)
def muman(x,y): t_max = x if x > y else y return t_max print(muman(10,20))
def func(x,y): print(x) print(y) func(10,20)
3、动态参数:*args接受(按位置传值多余的参数都由args接受)一个或多个参数,组成元组, **kwargs接受多个关键字参数,并组成字典类型
def func(*args,**kwargs): print(args) print(kwargs) func(1,2,3,4,5,x = 5,y = 6)
2,实参:真实存在的值,在函数调用时传入的值
实参:关键字参数
2、按关键字传参:就是以变量的形式和赋值的形式传参
def func(x,y): print(x) print(y) func(y=10,x=20)
参数之间的顺序:位置参数------动态参数(*args)-------默认参数----------关键字参数(**kwargs)
函数陷阱:
def defult_param(a,l =[]): l.append(a) #在形参l中传入了变量a print(l) #打印l defult_param(('alex')) #将alex传给了a,这时l中的a也传入了alex defult_param('egon') #将egon传给了l #结果['alex'] # ['alex','egon']
魔性用法:在函数调用的时候,可以打散 *args按顺序打散,**kwargs打散
def my_sum(*args): #聚合 print(args) sum_2 = 0 # for i in args: # sum_2 += i return sum_2 l = 'gsdfgsdf' # ret = my_sum(l[0],l[1],l[2],l[3]) #等于下面一步 # ret = my_sum(*l) #按顺序打散 ret = my_sum(*l) #将字符串的每一个字符打散出来 print(ret)
def func(**kwargs): #聚合 print(kwargs) func(b=2,a=1) dic = {'a':1,'b':2} func(**dic)
三,空间命名和作用域
什么叫命名空间:存放名字与值的关系的空间叫命名空间
1、三种空间命名(命名空间加载由硬盘到内存)
1,局部空间命名:程序运行中,调用时才加载,随之函数调用结束而结束
2、全局空间命名:程序运行中,从上到下加载(写在函数外面的变量名)
3、内置空间命名:运行程序前加载(python解释器本身自带的),启动python解释器就有的
******命名空间的加载顺序:启动python解释器加载内置命名空间,在加载全局命名空间,最后加载局部命名空间
2、空间命名的取值(从内往外取值)
1,局部调用时: 局部空间-------全局空间---------内置空间
2,全局调用时:全局空间-------内置空间
****命名空间的本质:存放名字和值的绑定关系。
3、作用域:命名空间和作用域是分不开的,因为作用域的划才得到的命名空间
1,全局作作用域:全局生效,包含内置名称空间和全局名称空间,在文件的任何位置都能别应用
2,局部作用域:局部空间名称,只能在局部范围之内才能生效
四,函数名本质
函数名本质就是函数的内存地址
1,可以被应用
2、可以当做函数的参数和返回值
3,可以被当做容器类型的元素
五,闭包
闭包函数:内部函数包含对外部作用域而非全局作用域名字的引用,该内部函数被称为闭包函数-------函数内部定义的函数称为内部函数
六 ,装饰器
1,装饰器的形成过程
import time def func1(): print('in func1') def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner func1 = timer(func1) func1()
语法糖、带参数的装饰器、hold的住所有函数、带返回值的装饰器
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer #==> func1 = timer(func1) def func1(): print('in func1') func1()
装饰器的本质:装饰器就是一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对函数的功能进行扩展
def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner @timer def func1(a): print(a) func1(1)
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func1 = timer(func1) def func1(a,b): print('in func1') @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func1('aaaaaa','bbbbbb') print(func2('aaaaaa'))
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func2('aaaaaa') print(func2('aaaaaa'))
def index(): '''这是一个主页信息''' print('from index') print(index.__doc__) #查看函数注释的方法 print(index.__name__) #查看函数名的方法
from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__) print(index.__name__)
2,装饰器的开放封闭原则
对扩展是开放的,对修改是封闭的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
3、装饰器的主要功能和装饰器的固定结构
装饰器的主要功能:在不改变调用方式的基础上在函数前后加功能
装饰器的固定结构
def time(func): def inner(*args,**kwargs): #函数执行之前要做的 ret=func(*args,**kwargs) #函数执行之后要做的 return ret return inner
from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper
4,带参数的装饰器
def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函数之前要做的''') re = func(*args,**kwargs) if flag: print('''执行函数之后要做的''') return re return inner return timer @outer(False) def func(): print(111) func()
5、多个装饰器装饰一个函数
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper2 @wrapper1 def f(): print('in f') f()
七,递归
递归的定义:就是一个函数调用自己本身
递归的最大深度-----------997(python为程序优化设定的一个默认值)
默认的递归最大限度为1000
递归经常和循环挂在一起
函数的每次调用都会产生一个自己的名称空间
import sys
print(sys.getrecursionlimit())
def foo(n): print(n) n+=1 foo(n) foo(1)
再谈递归
a比b大两岁,b比c大两岁,c比d大两岁,d比e大两岁,e40岁了
def age(n): if n==1: return 40 else: return age(n-1)+2 print(age(4))
def age(n): if n == 4: return 40 return age(n+1)+2 print(age(5))
递归和三级菜单
#三级菜单算法 menu = { '北京': { '海淀': { '五道口': { 'soho': {}, '网易': {}, 'google': {} }, '中关村': { '爱奇艺': {}, '汽车之家': {}, 'youku': {}, }, '上地': { '百度': {}, }, }, '昌平': { '沙河': { '老男孩': {}, '北航': {}, }, '天通苑': {}, '回龙观': {}, }, '朝阳': {}, '东城': {}, }, '上海': { '闵行': { "人民广场": { '炸鸡店': {} } }, '闸北': { '火车战': { '携程': {} } }, '浦东': {}, }, '山东': { '烟台':{ '绿海' }, '济南':{ '人名堂' }, }, '甘肃':{ '天水':{ '张家川':{ '西山村' }, }, }, } menu def threelm(menu): for i in menu: print(i) a=input('请输入:') if a in menu: threelm(menu[a]) threelm(menu)
递归函数与二分算法
二分查找算法------中间往两边找值
def func(l, aim,start = 0,end = len(l)-1 ): mid = (start+end)//2 if not l[start:end+1]: return elif aim > l[mid]: return func(l,aim,mid+1,end) elif aim < l[mid]: return func(l,aim,start,mid-1) elif aim == l[mid]: print("bingo") return mid index = func(l,68) print(index)