详解python高级函数有哪些及用法是什么
Admin 2022-11-02 群英技术资讯 750 次浏览
很多朋友都对“详解python高级函数有哪些及用法是什么”的内容比较感兴趣,对此小编整理了相关的知识分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获,那么感兴趣的朋友就继续往下看吧!命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。
len/eval/enumerate/bytes/max/min/sorted/map/filter....
如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:
NameError: name 'runoob' is not defined。
命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。
因此,我们无法从外部命名空间访问内部命名空间的对象。
如下图所示,相同的对象名称可以存在于多个命名空间中。

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。
全局名称空间和局部名称空间中可能会存在名字相同的变量,但是这两个变量互不影响。
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
Python的作用域一共有4种,分别是:
对于变量作用域,变量的访问以: L –> E –> G –>B 的 规则查找。
在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

举例:
x = 1
def func():
print(x) #10
x = 10
func()
内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。
在Python3.0中,可以使用以下的代码来查看到底预定义了哪些变量:
import builtins print(dir(builtins))
Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,
如下代码:实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。如果将 msg 定义在函数中,则它就是局部变量,外部不能访问。
if True:
msg = 'I am from Runoob'
print(msg)
# 'I am from Runoob'
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
# 作用域注意点
x = 1
def f1(): # 定义阶段x=1
print(x) #1
def f2():
x = 2 #此x为f2函数的局部变量,f1无法直接访问
f1()
f2()
def f1():
def inner():
print('from inner')
return inner
f = f1() # from inner 。把局部定义的函数inner()放在全局之中
def bar():
f()
bar()
函数内可以访问全局变量,但不能直接更新(修改)其值,可以加上 global 引用以更新变量值 :
x = 1
def f1():
x = 2
def f2():
global x # 修改全局
x = 3
f2()
f1()
print(x) # 3
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了
x = 1
def f1():
x = 2
def f2():
nonlocal x
x = 3
f2()
print(x) # 3
f1()
闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。
闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。
def outter(x):
x = 1
def inner():
print(x)
return inner #返回的是函数名(函数对象)
f = outter(2)
f() # 1
f() # 1
f() # 1
# 查看闭包的元素
print(f.__closure__[0].cell_contents) # 1
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。
延迟计算(原来我们是传参,现在我们是包起来)、爬虫领域。
import requests
def outter(url):
def get():
response = requests.get(url)
print(f"done: {url}")
return get
baidu = outter('https://www.baidu.com')
python = outter('https://www.python.org')
baidu()
baidu()
python()
python()
装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能。装饰器的实现必须遵循两大原则:
装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。
不改变函数体代码,并且不改变函数调用方式,它本质就是一个闭包函数。
def f1(x):
def f2():
print(x) # 10
return f2
f2 = f1()
f2() # f2()
在不改变当前函数的情况下, 给其增加新的功能:
def log(pr): # 将被装饰函数传入
def wrapper():
print("**********")
return pr() # 执行被装饰的函数
return wrapper # 将装饰完之后的函数返回(返回的是函数名)
@log
def pr():
print("我是小小洋")
pr()
# **********
# 我是小小洋
回调函数和返回函数的实例就是装饰器。
举例:
import time
def index():
print('welcome to index')
time.sleep(1)
def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
func()
end = time.time()
print(f"{func} time is {start - end}") # time is -1.0038220882415771
return wrapper
index = time_count(index) # index为被装饰函数index的内存地址,即index = wrapper
index() # wrapper()
如果原始的被装饰函数index()有返回值的时候,wrapper()函数的返回值应该和index()的返回值相同,也就是说,我们需要同步原始的index()和wrapper()方法的返回值。
import time
def index():
print('welcome to index')
time.sleep(1)
return 123
def time_count(func):
# func = 最原始的index
def wrapper():
start = time.time()
res1 = func()
end = time.time()
print(f"{func} time is {start - end}") # time is -1.0050289630889893
return res1
return wrapper
index = time_count(index)
res = index()
print(f"res: {res}") #
res: 123
如果原始的被装饰函数index()方法需要传参,那么我们之前的装饰器是无法实现该功能的,由于有wrapper()=index(),所以给wrapper()方法传参即可。
import time
def index():
print('welcome to index')
time.sleep(1)
return 123
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
return name
def time_count(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func} time is {start-end}") # time is -1.0039079189300537
return res
return wrapper
home = time_count(home)
res = home('egon')
print(f"res: {res}") #res: egon
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
在被装饰函数正上方,并且是单独一行写上@装饰器名
import time
def time_count(func): #装饰器
# func = 最原始的index
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func} time is {start-end}") # time is -1.0005171298980713
return res
return wrapper
@time_count # home = time_count(home)
def home(name):
print(f"welcome {name} to home page") #welcome egon to home page
time.sleep(1)
return name
res = home('egon')
print(f"res: {res}") #res: egon
注意无参装饰器只套两层。
import time
current_user = {'username': None}
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res1 = func(*args, **kwargs)
return res1
user = input('username: ').strip()
pwd = input('password: ').strip()
if user == 'nick' and pwd == '123':
print('login successful')
current_user['username'] = user
res1 = func(*args, **kwargs)
return res1
else:
print('user or password error')
return wrapper
@login
def index():
print('welcome to index')
time.sleep(1)
res = index()
#username: nick
#password: 123
#login successful
#welcome to index
我们首先看看三层闭包怎么运用。
def f1(y):
def f2():
x = 1
def f3():
print(f"x: {x}") # x: 1
print(f"y: {y}") # x: 1
return f3
return f2
f2 = f1(2)
f3 = f2()
f3()
在函数中嵌入装饰器
import time
current_user = {'username': None}
def auth(engine='file'):
def login(func):
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
if engine == 'file':
print('base of file')
if user == 'nick' and pwd == '123':
print('login successful')
current_user['username'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql, please base of file')
return wrapper
return login
@auth(engine='file')
def index():
print('welcome to index')
time.sleep(1)
res = index()
username: nick
password: 123
base of file
login successful
welcome to index
没错,装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。
class Foo(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')
@Foo
def bar():
print ('bar')
bar()
functools.wraps
使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了,比如函数的docstring、__name__、参数列表,先看例子:
# 装饰器
def logged(func):
def with_logging(*args, **kwargs):
print func.__name__ # 输出 'with_logging'
print func.__doc__ # 输出 None
return func(*args, **kwargs)
return with_logging
# 函数
@logged
def f(x):
"""does some math"""
return x + x * x
logged(f)
不难发现,函数 f 被with_logging取代了,当然它的docstring,__name__就是变成了with_logging函数的信息了。好在我们有functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器里面的 func 函数中,这使得装饰器里面的 func 函数也有和原函数 foo 一样的元信息了。
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print func.__name__ # 输出 'f'
print func.__doc__ # 输出 'does some math'
return func(*args, **kwargs)
return with_logging
@logged
def f(x):
"""does some math"""
return x + x * x
一个函数还可以同时定义多个装饰器,比如:
@a
@b
@c
def f ():
pass
它的执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于
f = a(b(c(f)))
现在我们来看一下装饰器在哪些地方特别耀眼,以及使用它可以让一些事情管理起来变得更简单。
装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
日志是装饰器运用的另一个亮点。这是个例子:
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
# Output: addition_func was called
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍了Python NumPy中diag函数的使用说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
假如我写了一个函数 fdef f(): print('hello')之后我想知道这段函数执行所要的时间,这好办,我只要将代码改为如下就行import timedef f(): start = time.time()
这篇文章主要为大家介绍了基于Python如何实现评论区抽奖的功能,文章的示例代码讲解详细,对我们学习Python有一定帮助,需要的朋友可以学习一下
这篇文章主要介绍了Python 制作子弹图,众所周知,Python 的应用是非常广泛的,今天我们就通过 matplotlib 库学习下如何制作精美的子弹图,需要的朋友可以参考一下
py_compile模块提供一个函数,用于从源文件生成字节码文件,以及在将模块源文件作为脚本调用时使用的另一个函数。虽然并不经常需要,但是在安装用于共享使用的模块时,这个函数非常有用,特别是如果某些用户可能没有权限在包含源代码的目录中编写字节码缓存文件的话。源代码不多,如下>>>importpy_compile>>>dir(py_c
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008