函数对象,函数的嵌套,名称空间与作用域,闭包,装饰器,迭代器,内置函数
Posted 龚旭1994
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数对象,函数的嵌套,名称空间与作用域,闭包,装饰器,迭代器,内置函数相关的知识,希望对你有一定的参考价值。
一,函数对象
函数对象:函数是第一类对象,即函数可以当做数据传递
1,可以被引用
def foo(): print(\'from foo\') func=foo print(func) print(foo()) func()
2,可以做参数的传递
def foo(): print(\'from foo\') def bar(func): print(func) bar(foo) foo()
3,返回值可以是函数
def foo(): print(\'from foo\') def bar(func): return func f=bar(foo) print(f) #打印foo的内存地址 f() #可直接调用,是foo的值
4,可以当作容器类型的元素
func_dic={ \'func\':func } func_dic[\'func\']()
二,函数嵌套
1,函数的嵌套调用
def max1(x,y): return x if x>y else y def max2(a,b,c): res=max1(a,b) res1=max1(res,c) return res1 print(max2(10,20,30))
2,函数的嵌套定义
函数的定义相当于变量的定义
def f1(): print(\'from f1\') def f2(): print(\'from f2\') def f3(): print(\'from f3\') f3() f2() f1()
三,名称空间与作用域
名称空间:存放名字的地方叫名称空间,存放这些值与名字的绑定关系
第一种 import builtins print(dir(builtins)) 第二种 import builtins for i in dir(builtins): print(i)
三种名称空间
x=1000 def func(y): x=2 print(locals()) #在局部能看见全局和局部 print(globals()) #在全局能看见全局,看不见局部 func(1)
查看全局作用域内名字的方法:gloabls()
查看全局作用域内名字的方法 :locals()
四,闭包
def f1(): x=1 def f2(): print(x) return f2 f=f1() f()
def f1(): x=1 y=1 def f2(): print(x,y) return f2 f=f1() print(f.__closure__) #显示值的个数 print(f.__closure__[0].cell_contents) #显示值,[]中选择显示第几个值
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
应用领域:延迟计算(原来我们是传参,现在我们是包起来)
五,装饰器(闭包函数的一种应用场景)
为什么要用装饰器?
1,开放封闭原则,对修改是封闭的,对扩展是开放的
2,装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为其添加新功能
装饰器:在遵循下面两个原则的前提下为被修饰者添加新功能
必须遵循两个原则:
1,尽量不要修改源代码
2,不能修改调用方式
装饰器:修饰别人的工具,修饰:添加功能,工具指的是函数
装饰器本身可以是任何可调用对象,被装饰的对象也可以是任意可调用对象
装饰器语法:
被装饰函数的正上方,单独一行
无参函数的简单语法
import time def timmer(func): def wrapper(): start_time=time.time() func() stop_time=time.time() print(\'run time is %s\' %(stop_time-start_time)) return wrapper @timmer def index(): time.sleep(3) print(\'welcome to index\') index()
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 index(): time.sleep(3) print(\'welcome to index\') return 3 @timmer def foo(name): time.sleep(1) print(\'from foo\') res=index() print(res) res1=foo(\'gx\') print(res1) index()
多个装饰器(有参装饰器的使用)
login={\'user\':None,\'status\':False} def auth(drive=\'file\'): def auth2(func): def wrapper(*args,**kwargs): print(\'======>>auth.wrapper\') if drive==\'file\': if login[\'user\'] and login[\'status\']: res=func(*args,**kwargs) return res else: name=input(\'用户名>>>>>>:\').strip() pwd=input(\'密码>>>>>>>:\').strip() if name == \'gx\' and pwd == \'123\': login[\'user\']=\'gx\' login[\'status\']=True print(\'login successful\') res=func(*args,**kwargs) return res else: print("login error") elif drive==\'ldap\': print(\'=====>>ldap的认证\') elif drive==\'mysql\': print(\'======>>mysql的认证\') return func(*args,**kwargs) else: print(\'未知的认证\') return wrapper return auth2 @auth(\'file\') def index(): print(\'welcome to index page\') index()
装饰器补充:
Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring
functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 __module__、__name__、__doc__,或者通过参数选择。
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__)
六,迭代器
为什么要有迭代器?
对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式
迭代的概念:重复+上一次迭代的结果为下一次迭代的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
执行__iter__方法,得到的结果就是迭代器
迭代器的有点和缺点:
优点:1,提供了一种不依赖下标的迭代方式
2,就迭代器本身来说,更节省内存
缺点: 1,无法获取迭代器对象的长度
2,不如序列类型取值灵活,是一次性的,只能往后取,不能往前退
迭代协议:
对象有__next__
对象有__iter__,对于迭代器来说,,执行__iter__方法,得到的结果仍然是它本身
while True: #只满足重复,因而不是迭代 # print(\'====>\') 迭代 l=[1,2,3] count=0 while count < len(l): #只满足重复,因而不是迭代 print(\'====>\',l[count]) count+=1
可迭代对象
[1,2].__iter__() \'hello\'.__iter__() (1,2).__iter__() {\'a\':1,\'b\':2}.__iter__() {1,2,3}.__iter__() f=open(\'a.txt\',\'w\') f.__iter__()
print(isinstance(\'abc\',Iterable)) print(isinstance([],Iterable)) print(isinstance((),Iterable)) print(isinstance({\'a\':1},Iterable)) print(isinstance({1,2},Iterable)) print(isinstance(f,Iterable)) 语法:isinstance(object,type) 作用:来判断一个对象是否是一个已知的类型。
只有文件是迭代器对象__next__是迭代器
__next__一次只能取一个值
抛出异常:StopIteration说明值已取完
取字典value的值和处理异常
dic={\'a\':1,\'b\':2,\'c\':3} i=dic.__iter__() while True: try: key=i.__next__() print(dic[key]) except StopIteration: break
生成器函数:只要函数体包括yield关键字,该函数就是yield就是生成器函数
yield的功能:
1,相当于为函数装好__iter__和__next__
2,return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行。
def foo(): print(\'first\') yield 1 print(\'second\') yield 2 print(\'third\') yield 3 print(\'fourth\') g=foo() for i in g: print(i)
def foo(): print(\'first\') yield 1 print(\'second\') yield 2 print(\'third\') yield 3 print(\'fourth\') g=foo() print(next(g)) print(next(g)) #触发迭代器g的执行,进而触发函数的执行 print(next(g)) print(next(g))
三元表达式
def max2(x,y): return x if x > y else y print(max2(1,2)) name=\'gongxu\' print(\'h\' if name == \'haha\' else \'gongxu\')
列表推导式
l=[\'egg%s\' %i for i in range(10)] print(l) l=[\'egg%s\' %i for i in range(10) if i >=5] print(l) names=[\'gx_xx\',\'liting_xx\',\'xiaohua\'] name_new=[name for name in names if name.endswith(\'xx\')] print(name_new)
生成器表达式(把[]变成()就是生成器表达式)
with open(\'a.txt\',encoding=\'utf-8\') as f: print(max([len(line) for line in f]) with open(\'a.txt\', encoding=\'utf-8\') as f: res=max(len(line) for line in f) print(res)
以上是关于函数对象,函数的嵌套,名称空间与作用域,闭包,装饰器,迭代器,内置函数的主要内容,如果未能解决你的问题,请参考以下文章
python基础之====函数对象函数嵌套名称空间与作用域装饰器
20181128(闭包函数,函数嵌套,名称空间,作用域,装饰器待补充)
函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数