python函数
阅读目录
一 函数知识体系 |
1 什么是函数? 2 为什么要用函数? 3 函数的分类:内置函数与自定义函数 4 如何自定义函数 语法 定义有参数函数,及有参函数的应用场景 定义无参数函数,及无参函数的应用场景 定义空函数,及空函数的应用场景 5 调用函数 如何调用函数 函数的返回值 函数参数的应用:形参和实参,位置参数,关键字参数,默认参数,*args,**kwargs 6 高阶函数(函数对象) 7 函数嵌套 8 作用域与名称空间 9 装饰器 10 迭代器与生成器及协程函数 11 三元运算,列表解析、生成器表达式 12 函数的递归调用 13 内置函数 14 面向过程编程与函数式编程
*args #接收多出来的位置参数,组成元组 **kwargs #接收多出来的关键字参数,组成字典
函数对象的概念: 1.函数可被当做数据传递 2.函数可以当做参数传给另外一个函数 3.一个函数的返回值可以是一个函数
二 闭包函数 |
def get(url): return urlopen(url).read() print(get('http://www.baidu.com')) print(get('http://www.baidu.com'))
def get(url): def inner(): return urlopen(url).read() return inner baidu=get('http://www.baidu.com') print(baidu()) print(baidu())
def get(url): def inner(): return urlopen(url).read() return inner baidu=get('http://www.baidu.com') print(baidu.__closure__) print(baidu.__closure__[0].cell_contents) #打印 (<cell at 0x0000000001E1C528: str object at 0x0000000001DB5C70> http://www.baidu.com
三 装饰器 |
import time def index(): time.sleep(3) print('首页面') #实现 def timer(func): def inner(): start_time=time.time() func() stop_time=time.time() print('耗时[%s]'%(start_time-stop_time)) return inner index=timer(index) index() #这样就不但没有修改源码以及调用方式就添加上了新功能: #原因是直接把内部函数inner赋值给index,但是index上面还包了一层,inner就可以用上面那层的参数
import time def timer(func): def inner(): start_time=time.time() func() stop_time=time.time() print('耗时[%s]'%(stop_time-start_time)) return inner
@timer def index(): time.sleep(3) print('首页面') index()
解释:当程序运行到@time时python会把正下方index当做参数传给time函数,返回inner又赋给index,此时的index就已经是inner的内存地址了,可以加括号执行inner,但是inner上面还包了一层,inner函数可以直接用上面一层的参数。
import time def timer(func): def inner(*args,**kwargs): start_time=time.time() func(*args,**kwargs) stop_time=time.time() print('耗时[%s]'%(stop_time-start_time)) return inner @timer def home(name): time.sleep(2) print('欢迎%s回家'%name) home('dick')
解释:
很明显现在被装饰的函数带了一个参数,在home被调用的时候其实调用的是time下的inner,(解释:遇到@time装饰器的时候他会把下面的函数当做参数传给time装饰器,并返回inner函数的内存地址赋值给home)inner函数就必须接收,但是接受到的值不是这个函数用,他要原封不动的再传给真正被调用的函数就是func,func变量存的参数正在home函数的内存地址。
import time def timer(func): def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('耗时[%s]'%(stop_time-start_time)) return res return inner @timer def home(name): time.sleep(2) print('欢迎%s回家'%name) return 'home' res=home('dick') print(res)
#打印 欢迎dick回家 耗时[2.0001144409179688] home
解释:
要拿到被装饰对象的返回值得话必须在他被调用的地方获取返回值。如下咧:调用home并不是调用正在的home,而是再调inner,inner里面的func才是在调用真正的home,所以要在调用func时,func执行完之后把返回值返回,把返回值保存下来赋值给res,inner执行执行完之后,把func返回值在返回给inner的调用者(就是home),然后调用者接收,打印。
import time def timer(func): def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('耗时[%s]'%(stop_time-start_time)) return res inner.__doc__=func.__doc__ return inner @timer def home(name): ''' home的帮助文档 :param name: :return: ''' time.sleep(2) print('欢迎%s回家'%name) return 'home' res=home('dick') print(help(home)) #打印 欢迎dick回家 耗时[2.0001139640808105] Help on function inner in module __main__: inner(*args, **kwargs) home的帮助文档 :param name: :return: None home
from functools import wraps import time def timer(func): @wraps(func) def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('耗时[%s]'%(stop_time-start_time)) return res return inner @timer def home(name): ''' home的帮助文档 :param name: :return: ''' time.sleep(2) print('欢迎%s回家'%name) return 'home' res=home('dick')
#有问题的代码 def auth(func): def inner(*args,**kwargs): if user['user']: res=func(*args,**kwargs) return res if cmd == 'file': name=input('username>>') pwd=input('password>>') if name =='admin' and pwd=='123': user['user']=user res=func(*args,**kwargs) return res elif cmd == 'mysql': print('mysql auth') else: pass return inner
解决
def auth(cmd): def wrapper(func): def inner(*args,**kwargs): if user['user']: res=func(*args,**kwargs) return res if cmd == 'file': name=input('username>>') pwd=input('password>>') if name =='admin' and pwd=='123': user['user']=user res=func(*args,**kwargs) return res elif cmd == 'mysql': print('mysql auth') else: pass return inner return warpper def home(name): time.sleep(2) print('欢迎%s'%name) return 'home' #调用的方法 wrapper=auth('file') home=wrapper(home) home('dick')
import time user={'user':None} def auth(cmd): def wrapper(func): def inner(*args,**kwargs): if user['user']: res=func(*args,**kwargs) return res if cmd == 'file': name=input('username>>') pwd=input('password>>') if name =='admin' and pwd=='123': user['user']=user res=func(*args,**kwargs) return res elif cmd == 'mysql': print('mysql auth') else: pass return inner return wrapper @auth('mysql') #函数执行完这个地方就是@wrapper装饰器了 def home(name): time.sleep(2) print('欢迎%s'%name) return 'home' #调用的方法 home('dick') #其实就是在执行inner
解释:
代码从上到下执行,碰见@auth(‘mysql’),这时看见名字加括号就下面先不用管直接调用auth,并把参数‘mysql’传给他,并返回wrapper的内存地址,这时@那个地方就是wrapper装饰器了(auth函数只不过是给装饰器传了参数)。这时@wrapper就把正下方的home函数内存地址当做参数传给wrapper自己,并返回inner函数的内存地址赋值给home,此时的home已经不是被装饰对象的被装饰对象已经刚刚被当做参数传给了wrapper,此时的home是最里层的inner函数,作用是接收被装饰对象的参数,然后执行func(这时的func就是被装饰对象),然后把inner接收的值在原封不动的传给func(被装饰对象)
import time user={'user':None} def auth(cmd): def wrapper(func): def inner(*args,**kwargs): if user['user']: res=func(*args,**kwargs) return res if cmd == 'file': name=input('username>>') pwd=input('password>>') if name =='admin' and pwd=='123': user['user']=user res=func(*args,**kwargs) return res elif cmd == 'mysql': print('mysql auth') res=func(*args,**kwargs) return res else: pass return inner return wrapper
def timer(func): def inner(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('耗时[%s]'%(stop_time-start_time)) return res return inner @auth('file') @timer def home(name): time.sleep(2) print('欢迎%s'%name) return 'home' #调用的方法 home('dick')
解释:
直接在被装饰对象的正上方,加上需要装饰的功能即可。在遇到@auth('file')装饰器时因为用的事mysql认证所有执行mysql的if分支,运行func函数(func函数就是被装饰对象函数的内存地址),但是在被装饰对象是发现还有一个装饰器@timer(这是一个无参装饰器)于是time就把被装饰对象的内存地址传给自己,然后又给添加上了统计时间功能。
|
简介
def func(a): if a ==1: return 18 return func(a-1)+2 print(func(5)) #打印 26
解释:
定义了一个func的函数传一个参数就是那五个人的个数,先判断人的个数是不是已经到了第一个了如果到了就返回18,如果还没有到第一个人就继续减1加二知道取到第一个人返回十八接下来就是回溯阶段给18加上了4次2,每次调用在括号外面加2意思就是给返回值加二就是最后那个18
l=[1,2,[3,4,[5]]] def func(l_list): for i in l_list: if type(i) == list: func(i) else: print(i) func(l) #打印 1 2 3 4 5
解释:
直接使用递归调用,for循环这个列表判断每一个元素如果函数列表就再次调自己进行递归,再循环这个列表直到递归结束,如果不是列表了就直接打印元素
l=[1,2,10,30,33,99,101,200,301,402] def func(num,l): print(l) if l: mid=len(l)//2 if num > l[mid]: l=l[mid+1:] elif num < l[mid]: l=l[:mid] else: print('ok') return func(num,l) else: print('no') func(30,l) #打印 [1, 2, 10, 30, 33, 99, 101, 200, 301, 402] [1, 2, 10, 30, 33] [30, 33] [30] ok #没有值打印 [1, 2, 10, 30, 33, 99, 101, 200, 301, 402] [1, 2, 10, 30, 33] [30, 33] [30] [] no
解释:
定义一个函数利用递归调用,第一层if判断是为了想要的值没有在列表里面而递归到最后没有找到防止报错用的,列表都切空了都没有找到值说明里面就没有想要的值。如果列表里面还有值就切分唯二,利用二分法形式,判断用户传的值是大于还是小于中间这个值,判断完成后直接切分,把切分的那部分列表在递归下去再判断列表是不是空的,如果是空的就说明没有值,如果还有值还继续判断中间值是大于小于还是等于用户传来的值,以此类推。
l=[1,2,10,30,33,99,101,200,301,402] def func(num,l): if l: mid=len(l)//2 if num > l[mid]: l=l[mid+1:] elif num < l[mid]: l=l[:mid] else: return num return func(num,l) else: print('no') return None res=func(200,l) if res: print(l.index(res)) #打印 7
五 匿名函数 |
salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 } #求最大值得函数 print(max(salaries,key=lambda n:salaries[n])) #打印 alex #按工资多少排序 print(sorted(salaries,key=lambda n:salaries[n])) #打印 ['yuanhao', 'egon', 'wupeiqi', 'alex']
解释:
max函数就是求最大值得函数但是你要是直接把字典丢进去的话,那默认比较的是字典的key,max函数就是一个迭代器,他也是循环这个字典取出每一个key,但是max函数里面有一个key的参数,这个参数的作用就是你把取出来的值别做处理了交个我后面这个功能,此时key后面就是一个匿名函数了,匿名函数也有一个参数作用就是接收max函数循环字典取出的key,冒号后面就是匿名函数的函数体,匿名函数自带return,返回字典里面的value所以max的比较条件就不是字典里面的key了而是value。
name=['admin','root','dick'] res=map(lambda x:x+'_sb',name) print(list(res)) #打印 ['admin_sb', 'root_sb', 'dick_sb']
解释:
这个方法是把可可迭代对象放在后面,功能放在前面,map函数不断循环列表的面值交给匿名函数,匿名函数就会把每个元素后面都加上了指定了_sb
print(list(map(lambda x,y:x+y,[1,2,3],[1,2,3]))) #打印 [2, 4, 6]
from functools import reduce print(reduce(lambda x,y:x+y,range(1,101))) #打印 5050
解释:
和其他内置函数一样,也是for循环后面的range,这次是需要两个参数是在range里面取到两个数值后进行加法运算得出一个结果后,再到range里面取一个数值和刚才得出结果的数值在进行加法运算以此类推。
from functools import reduce print(reduce(lambda x,y:x+y,range(1,101),100)) #打印 5150
from functools import reduce print(reduce(lambda x,y:x+y,[1,2,3])) #打印 6
name=['admin_sb', 'root_sb', 'dick_sb','meng'] res=filter(lambda name:name.endswith('sb'),name) print(list(res)) #打印 ['admin_sb', 'root_sb', 'dick_sb']
解释:
他还是把功能放在前面,可迭代对象放在后面,内置还是用for循环,在可迭代对象里面取出一个值放到前面的匿名函数里面,判断看看这个元素的末尾是不是由sb关键字,有就返回留下来。
print(abs(-5)) #打印 5
name=['admin_sb', 'root_sb', 'dick_sb','meng',] print(all(name)) #打印 true name=['admin_sb', 'root_sb', 'dick_sb','meng',''] print(all(name)) #打印 false
l=[[],'',0,1] print(any(l)) #打印 true print(any([])) #打印 false
print(bin(10)) #打印 0b1010
print(oct(10)) #打印 0o12
print(hex(10)) #打印 0xa
print(bytes('hello',encoding='utf8')) #打印 b'hello'
print(callable(map)) #打印 true
print(chr(65)) print(chr(90)) print(chr(97)) print(chr(122)) #打印 A Z a z
print(ord('a')) print(ord('z')) #打印 97 122
import time print(dir(time)) #打印 ['altzone', 'asctime', 'clock', 'ctime', 'daylight'......]
print(divmod(10,3)) #打印 (3,1)
l=['a','b','c'] for i,k in enumerate(l): print(i,k) #打印 0 a 1 b 2 c
def func(): ''' 帮助信息 :return: ''' pass print(help(func)) #打印 Help on function func in module __main__: func() 帮助信息 :return: None
print(isinstance(1,int)) #打印 true
print(pow(10,2)) #打印 100
l=['a','b','c','d','e','f'] l1=['a','b','c','d','e','f'] l2=['a','b','c','d','e','f']
res=slice(1,6,2) print(l[res]) print(l1[res]) print(l2[res]) #打印 ['b', 'd', 'f'] ['b', 'd', 'f'] ['b', 'd', 'f']
print(sum([1,2,3,4])) print(sum(range(10))) #打印 10 45
res=__import__('time') res.sleep(3)
七 迭代器 |
l=['a','b','c'] count=0 while count < len(l): print(l[count]) count+=1
l=['a','b','c'] count=0 while count < len(l): print(l[count]) count+=1
l={'a':1,'b':2,'c':3} l_dic=l.__iter__() print(l_dic.__next__()) print(next(l_dic)) print(next(l_dic)) print(next(l_dic)) #打印 a b c StopIteration
with open('test','r') as f: print(next(f),end='') print(next(f),end='') print(next(f),end='') #打印 1111 2222 3333
l={'a':1,'b':2,'c':3} l_doc=l.__iter__() while True: try: print(next(l_doc)) except StopIteration: break #打印 a b c
dic={'a':1,'b':2,'c':3} for i in dic: print(i) #打印 a b c
解释:
in后面的类型必须是可迭代对象(那他是不是迭代器对象呢?不一定),如果后面的类型就是迭代器对象也会执行他的__iter__方法只不过还是它本身。它会帮我们把可迭代对象,做成迭代器对象,遍历完所有值还会自动捕捉异常。
from collections import Iterator,Iterable print(isinstance('aaa',Iterable)) print(isinstance('aaa',Iterator)) #打印 True False
八 生成器 |
def func(): print('aaa') yield 1 print('bbb') yield 2 print('ccc') yield 3 res=func() print(res) res.__next__() res.__iter__() #打印 <generator object func at 0x00000000021FF4C0>
解释:
执行了func函数按理说是直接打印里面的内容可是现在却没有反应,打印它返回的结果是一个生成器对象内存地址。
def func(): print('aaa') yield 1,2,3 print('bbb') yield 2 print('ccc') yield 3 res=func() print(res.__next__()) print(res.__next__()) print(res.__next__()) #打印 aaa (1,2,3) bbb 2 ccc 3
def func(): print('aaa') yield 1 print('bbb') yield 2 print('ccc') yield 3 res=func() for i in res: print(i) #打印 aaa 1 bbb 2 ccc 3
练习
def my_range(start,stop,set=1): while start <= stop: yield start start+=set for i in my_range(1,5): print(i) #打印 1 2 3 4 5
import time def log(log): with open(log,'r') as f: f.seek(0,2) while True: line=f.read() if line: yield line else: time.sleep(0.2) def grep(line,keywords): for i in line: if keywords in i: print(i) grep(log('test'),'404')
import time def log(log): with open(log,'r') as f: f.seek(0,2) while True: line=f.read() if line: yield line else: time.sleep(0.2) def grep(line,keywords): for i in line: if keywords in i: yield i res=grep(log('test'),'404') for i in res: print(i)
def eater(name): print('%s 开动啦'%name) while True: food=yield 123 print('%s 开始吃 %s'%(name,food)) g=eater('admin') g.send(None) g.send('骨头') next(g) g.send('肉') #打印 admin 开动啦 admin 开始吃 骨头 admin 开始吃 None admin 开始吃 肉
def eater(name): food_list=[] print('%s 开动啦'%name) while True: food=yield food_list print('%s 开始吃 %s'%(name,food)) food_list.append(food) g=eater('admin') g.send(None) g.send('骨头') print(g.send('肉')) #打印 admin 开动啦 admin 开始吃 骨头 admin 开始吃 肉 ['骨头', '肉']
def a(): while True: x=yield print(x) b=a() b.send(None) b.send(1) b.send(2) b.send(3) #打印 1 2 3
import os def init(func): def inner(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return inner def seach(path_file,oppen_yield): g = os.walk(path_file) for path,_,file in g: for files in file: oppen_yield.send(r"%s\%s"%(path,files)) @init def oppen(cat_yield): while True: path_file=yield with open(path_file,'rb') as f: cat_yield.send((f,path_file)) @init def cat(grep_yield): while True: file_open,file_path=yield for line in file_open: res=grep_yield.send((line,file_path)) if res: break @init def grep(keywords,pinrter_yield): keywords=keywords.encode('utf8') while True: file_cat,file_path=yield if keywords in file_cat: yield True pinrter_yield.send(file_path) @init def pinrter(): while True: pinrter_yield=yield print(pinrter_yield) seach(r'D:\PycharmProj\fhm\老男孩', oppen(cat(grep('你好',pinrter()))))
九 三元表达式,生成器表达式,列表解析 |
name=input('>>') print('nb' if name=='dick' else 'sb') #打印 >>dick nb
print(['egg%s'%i for i in range(5)]) #打印 ['egg0', 'egg1', 'egg2', 'egg3', 'egg4']
print(['egg%s'%i for i in range(5) if i >=3]) #打印 ['egg3', 'egg4']
g=['a','b','c'] print([i.upper() for i in g if not i=='a']) #打印 ['B', 'C']
g=('egg%s'%i for i in range(5) if i >= 3) print(next(g)) #打印 egg3