首页 / PYTHON / python----函数进阶
python----函数进阶
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python----函数进阶,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5006字,纯文字阅读大概需要8分钟。
内容图文
名称空间
又名name space, 顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方
名称空间共3种,分别如下:
1.locals: 是函数内的名称空间,包括局部变量和形参
2.globals: 全局变量,函数定义所在模块的名字空间
3.builtins: 内置模块的名字空间
有名称空间才有作用域
例子:
def outer_function(): b = 20 def inner_func(): c = 30 a = 10
在这个例子中,名称a在全局名称空间中,名称b在函数outer_function的局部名称空间,名称c则在函数inner_func的局部名称空间。
当我们在函数inner_func时,c是个局部的名称,b是个非局部的名称,而a则是个全局的名称。在函数inner_func中,我们可以对c进行读取操作和赋值操作,而只能对b和a进行读取操作。当对b进行赋值时,一个新的名称将会被创建,这个新的名称处于inner_func函数局部名称空间中。对a进行赋值时也会在局部名称空间中创建一个新的名称。
def outer_function(): a = 20 def inner_function(): a = 30 print(‘a = %s‘ % a) inner_function() print(‘a = %s‘ % a) a = 10 outer_function() print(‘a = %s‘ % a) 输出: a = 30 a = 20 a = 10
在函数inner_function
中,我们对a
进行了赋值操作,但函数outer_function
中的a
仍然为20
,全局名称空间中的a
则仍然为10
。
为了在函数作用域中对全局的名称进行读取或者赋值操作,需要将这个名称声明为global
。
def outer_function(): global a a = 20 def inner_function(): global a a = 30 print(‘a = %s‘ % a) inner_function() print(‘a = %s‘ % a) a = 10 outer_function() print(‘a = %s‘ % a)
输出:
a = 30
a = 30
a = 30
可以看到,通过global
,我们在不同的作用域对全局名称a
进行了赋值操作,最后在函数inner_function
中对a
的赋值也就是全局名称a
的值。
作用域查找顺序:
- locals 是函数内的名字空间,包括局部变量和形参
- enclosing 外部嵌套函数的名字空间
- globals 全局变量,函数定义所在模块的名字空间
- builtins 内置模块的名字空间
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
level = ‘L0‘ n = 22 def func(): level = ‘L1‘ n = 33 print(locals()) def outer(): n = 44 level = ‘L2‘print(locals(),n) def inner(): level = ‘L3‘print(locals(),n) #此外打印的n是多少? inner() outer() func()
闭包:
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
闭包函数必须满足两个条件:
1.函数内部定义的函数
2.包含对外部作用域而非全局作用域的引用
例1:以下仅仅在函数内部定义了一个函数,但并非闭包函数.
def outer(): def inner(): print("inner func excuted") inner() # 调用执行inner()函数print("outer func excuted") outer() # 调用执行outer函数####输出结果为##########inner func excuted outer func excuted
例2:以下在函数内部定义了一个函数,而且还引用了一个外部变量x,那么这个是闭包函数么?答案:不是
x = 1 def outer(): def inner(): print("x=%s" %x) # 引用了一个非inner函数内部的变量print("inner func excuted") inner() # 执行inner函数print("outer func excuted") outer() #####输出结果######## x=1 inner func excuted outer func excuted
例3:显然,下面实例满足闭包函数的条件。现在,你应该清楚,作为一个闭包函数,必须得满足上述的两个条件,缺一不可。
def outer(): name = ‘alex‘def inner(): print("在inner里打印外层函数的变量",name) return inner f = outer() f()
装饰器:
装饰器:外部函数传入被装饰函数名,内部函数返回装饰函数名。
特点:1.不修改被装饰函数的调用方式 2.不修改被装饰函数的源代码
不带参数装饰器:
user_status = False # 用户登录了就把这个改成Truedef login(func): def inner(): _username = "alex"# 假装这是DB里存的用户信息 _password = "abc123"# 假装这是DB里存的用户信息global user_status if user_status == False: username = input("user:") password = input("pasword:") if username == _username and password == _password: print("welcome login....") user_status = True else: print("wrong username or password!") if user_status == True: func() return inner # henan()def home(): print("---首页----") def america(): print("----欧美专区----") def japan(): print("----日韩专区----") @login # henan=login(henan)def henan(): print("----河南专区----") henan() japan()
带参数的装饰器:
user_status = False # 用户登录了就把这个改成Truedef login(auth_type): def outer(func): def inner(*args, **kwargs): _username = "alex"# 假装这是DB里存的用户信息 _password = "abc123"# 假装这是DB里存的用户信息global user_status if user_status == False: username = input("user:") password = input("pasword:") if username == _username and password == _password: print("welcome login....") user_status = True else: print("wrong username or password!") if user_status == True: func(*args, **kwargs) return inner # henan()return outer def home(): print("---首页----") def america(): print("----欧美专区----") # @logindef japan(): print("----日韩专区----") @login(‘wx‘) # henan=login(henan)def henan(style): print("----河南专区----", style) # xx = login(‘qq‘) # print(xx) # henan = xx(henan) # print(henan) henan(‘oo‘)
列表生成式:
例子:
现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
,要求你把列表里的每个值加1,你怎么实现?
a = [i+1 for i in range(10)] print(a)
这样的写法就叫做列表生成式.
生成器:
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(1)) >>>next(g) >>>1 >>> next(g) <generator object <genexpr> at 0x1022ef630
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator.
所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
def fib(max): n, a, b = 0, 0, 1 while n < max: print(‘before‘) yield b # 把函数的执行过程冻结着这一步并且把b的值返回给外面print(b) a, b = b, a + b n = n + 1 return‘Done‘ f = fib(15) # turn function into generatorsfor i in f: print(i)
这里,最难理解的就是generator和函数的执行流程不一样。
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
而变成generator的函数,在每次调用next()的时候执行,
遇到yield语句返回,再次被next()调用时从上次返回的yield语句处继续执行
yield VS return:
- return返回并中止function
- yield返回数据,并冻结当前的执行过程
- next唤醒yield并继续执行,直到下一次遇到yield
原文:https://www.cnblogs.com/cnike/p/10662275.html
内容总结
以上是互联网集市为您收集整理的python----函数进阶全部内容,希望文章能够帮你解决python----函数进阶所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。