目录
一.函数对象
二.函数的嵌套
三.函数名称空间与作用域
四.闭包函数
五.无惨装饰器简单实现
六.装饰器的流程分析及修订
七.有参装饰器的实现及附加多个装饰器流程分析
八.叠加多个装饰器
九.迭代器
十.生成器
十一.内置函数
一:函数对象:函数是第一类对象,即函数可以当作数据传递1. 可以被引用
def foo(): print('from foo') func=foo print(foo) print(func) func()
2. 可以当作参数传递
def foo(): print('from foo') def bar(func): print(func) func() # 这里在执行foo() 并打印结果 bar(foo) # 这里执行函数bar() 传入的参数func就是foo地址
3. 返回值可以是函数
def foo(): print('from foo') def bar(func): return func f=bar(foo) print(f) f()
4. 可以当作容器类型的元素
def foo(): print('from foo') dic={'func':foo} #这里的value-foo就是函数的地址 print(dic['func']) dic['func']()
#利用该特性,优雅的取代多分支的ifdef foo(): print('foo')def bar(): print('bar')dic={ 'foo':foo, 'bar':bar, }while True: choice=input('>>: ').strip() if choice in dic: dic[choice]()
#应用def select(sql): print('========>select')def insert(sql): print('========>add')def delete(sql): print('=======>delete')def update(sql): print('-=---->update')func_dic={ 'select':select, 'update':update, 'insert':insert, 'delete':delete}def main(): while True: sql = input('>>: ').strip() if not sql:continue l = sql.split() cmd=l[0] if cmd in func_dic: func_dic[cmd](l)main()# 这是上面的复杂版def main(): sql = input('>>: ') l = sql.split() print(l) if l[0] == 'select': select(l) elif l[0] == 'insert': insert(l) elif l[0] == 'delete': delete(l) elif l[0] == 'update': update(l)
main()
二:函数的嵌套 1 函数的嵌套调用
def max(x,y): return x if x > y else y def max4(a,b,c,d): res1=max(a,b) res2=max(res1,c) res3=max(res2,d) return res3 print(max4(1,2,3,4))
2 函数的嵌套定义
def f1(): def f2(): def f3(): print('from f3') f3() f2() f1() f3() #报错 f2和f3是被包含在里边的 无法找到
三 名称空间和作用域: A.名称空间定义:名字与值的绑定关系 3种名称空间: 1.内置名称空间:随着python解释器启动而产生 print(sum) #sum就是解释器内置的名称 2.全局名称空间:文件执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间
x=1 def func(): money=2000 x=2 print('func') func() print(x) # x = 1 print(money) # money找不到值
3.局部名称空间:调用函数时会产生局部命名空间,只在函数调用时绑定,调用结束解绑定
x=10000 def func(): x=1 def f1(): pass
B.作用域即范围(作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关) 1.全局作用域( 查看使用 gloabls() ):内置名称空间,全局名称空间 2.局部作用域( 查看使用 locals() ):局部名称空间 LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ locals 是函数内的名字空间,包括局部变量和形参 enclosing 外部嵌套函数的名字空间(闭包中常见) globals 全局变量,函数定义所在模块的名字空间 builtins 内置模块的名字空间名字查找顺序:局部--》全局--》内置空间
# 反例 这里的变量就找不到 最终报错 def func(): x=2 func() print(x) # 所处位置就是全局
#全局作用域:全局有效,在任何位置都能被访问到,除非del删掉,否则会一直存活到文件执行完毕#局部作用域的名字:局部有效,只能在局部范围调用,只在函数调用时才有效,调用结束就失效
x=1 def f1(): print(x) def foo(): print(x) def f(x): # x=4 def f2(): # x=3 def f3(): # x=2 print(x) f3() f2() f(4)
四:闭包:内部函数包含对外部作用域而非全局作用域的引用 def counter(): n=0 def incr(): nonlocal n x=n n+=1 return x return incr c=counter() print(c()) print(c()) print(c()) print(c.__closure__[0].cell_contents) #查看闭包的元素闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域应用领域:延迟计算from urllib.request import urlopendef index(url): def get(): return urlopen(url).read() return getbaidu=index('http://www.baidu.com')print(baidu().decode('utf-8'))五: 装饰器1 为何要用装饰器: 开放封闭原则:对修改封闭,对扩展开放2 什么是装饰器 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。3. 先看简单示范
import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print('from foo') foo()
4.
def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': if name == 'egon' and pwd == '123': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('egon')
5. 装饰器语法: 在被装饰函数的正上方,单独一行 @deco1 @deco2 @deco3 def foo(): pass foo=deco1(deco2(deco3(foo)))六:迭代器 迭代的概念:重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值 # while True: #只满足重复,因而不是迭代 # print('====>') #迭代 l=[1,2,3] count=0 while count < len(l): #只满足重复,因而不是迭代 print('====>',l[count]) count+=1 为何要有迭代器? --对于没有索引的数据类型,必须提供一种不依赖索引的迭代器 可迭代的对象? --内置__iter__方法的,都是可迭代的对象 迭代器? --执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法 l={'a':1,'b':2,'c':3,'d':4,'e':5} i=l.__iter__() #等于i=iter(l) print(next(i)) print(next(i)) print(next(i)) StopIteration? 异常处理方法
while True: try: # 把可能异常的写到try里面 k=next(i) print(k) except StopIteration: # 捕捉异常 异常的话break break
i={'a':1,'b':2,'c':3}.__iter__() print(i.__next__()) print(i.__next__()) print(i.__next__()) print(i.__next__()) # 这里取道的是字典的key dic={'a':1,'b':2,'c':3} # 用key来取字典的value i=dic.__iter__() while True: try: key=i.__next__() print(dic[key]) except StopIteration: break
len(s) == s.len()s.__iter__ == iter(s)
dic={'name':'egon','age':18,'height':'180'} # 迭代字典生成元素为元组 print(dic.items()) for k in dic.items(): # for循环就相当于一个迭代器 得到的值就是字典的key print(k) # for循环的实现过程如下: i=iter(dic) while True: try: k=next(i) print(k) except StopIteration: break
迭代器的优缺点: 优点: 1.提供统一的且不依赖于索引的迭代方式 2.惰性计算,就迭代器本身节省内存;使用时 next()方法取值 缺点: 1.无法获取迭代对象长度 2.不如序列类型灵活,一次性的,只能往后走,不能往前退
# 对一个列表 l=[10000,2,3,4,5] i=iter(l) print(i) print(next(i)) # 要想使用这个值 就next()方法 # 对一个文件 文件本身就是一个好迭代器 f=open('a.txt',encoding='utf-8') #for line in f.readlines(): 这样的话都读到内存里边 占用内存 # print(line) print(next(f)) for line in f: # 遍历文件内容使用这个for print(line)
七 生成器 yield功能: 1.把函数做成迭代器,相当于为函数封装好__iter__和__next__ 2.对比return,可以返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
# def foo(): # return 1 # return 2 # return 3 # # res=foo() # print(res) def foo(): yield 1 yield 2 yield 3 res=foo() print(res) from collections import Iterable,Iterator print(isinstance(res,Iterator)) print(next(res)) print(next(res)) print(next(res))
应用一:计数功能counter
def counter(n): print('start') i=0 while i < n: yield i i+=1 print('end') c=counter(5) # print(next(c)) #0 # print(next(c)) #1 # print(next(c)) #2 # print(next(c)) #3 # print(next(c)) #4 # print(next(c)) --->没有yield,抛出StopIteration for i in counter(5): print(i)
应用二: 模拟管道tail -f a.txt |grep 'python'
# 管道左边的输出结果给到右边的grep 并执行查找‘python’;# tail功能是多次返回值,所以这里使用yield实现import time def tail(filepath): # filepath 文件路径 with open(filepath,encoding='utf-8') as f: f.seek(0,2) while True: line=f.readline() if line: yield line else: time.sleep(0.5) def grep(pattern,lines): for line in lines: if pattern in line: yield line for i in grep('python',tail('a.txt')): print(i)
来源:https://www.cnblogs.com/lipingzong/p/6896911.html