我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python命名空间、作用域和装饰器怎么使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python命名空间、作用域和装饰器怎么使用

今天小编给大家分享一下Python命名空间、作用域和装饰器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    一、名称空间和作用域

    1、命名空间(Namespace)

    命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。

    命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

    1、一般有三种命名空间:
    • 内置名称空间(built-in names):存放内置的名字,如len/eval/enumerate/bytes/max/min/sorted/map/filter....

    • 全局名称空间(global names):模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。

    • 局部名称空间(local names):函数内部的名字都是局部名称空间,不同函数内部的名字互不干涉。

    Python命名空间、作用域和装饰器怎么使用

    2、命名空间查找顺序:

    如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:

    NameError: name 'runoob' is not defined。
    • 查找顺序:假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间

    • 执行顺序:先内置(Python解释器启动的时候才会生成)-> 全局(文件执行的时候才会生成)-> 局部(函数调用的时候才会生成)

    3、命名空间的生命周期:

    命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。

    因此,我们无法从外部命名空间访问内部命名空间的对象。

    如下图所示,相同的对象名称可以存在于多个命名空间中。

    Python命名空间、作用域和装饰器怎么使用

    2、作用域:

    作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

    全局名称空间和局部名称空间中可能会存在名字相同的变量,但是这两个变量互不影响。

    Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

    变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。

    Python的作用域一共有4种,分别是:

    • L(Local):最内层,包含局部变量,比如一个函数/方法内部。

    • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。

    • G(Global):当前脚本的最外层,比如当前模块的全局变量。

    • B(Built-in): 包含了内建的变量/关键字等。,最后被搜索

    对于变量作用域,变量的访问以: L –> E –> G –>B 的 规则查找。

    在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

    Python命名空间、作用域和装饰器怎么使用

    举例:

    x = 1def func():    print(x)  #10x = 10func()

    内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。

    在Python3.0中,可以使用以下的代码来查看到底预定义了哪些变量:

    import builtinsprint(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'

    3、全局变量和局部变量

    定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

    局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

    # 作用域注意点x = 1def f1():  # 定义阶段x=1    print(x)  #1def f2():    x = 2  #此x为f2函数的局部变量,f1无法直接访问    f1()f2()

    4、函数对象+作用域应用

    def f1():    def inner():        print('from inner')    return innerf = f1()  # from inner   。把局部定义的函数inner()放在全局之中def bar():    f()bar()

    5、global关键字修改全局作用域中的变量

    函数内可以访问全局变量,但不能直接更新(修改)其值,可以加上 global 引用以更新变量值 :

    x = 1def f1():    x = 2    def f2():        global x  # 修改全局        x = 3    f2()f1()print(x)  # 3

    6、nonlocal关键字修改嵌套作用域中的变量。

    如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了

    x = 1def f1():    x = 2    def f2():        nonlocal x        x = 3    f2()    print(x)  # 3f1()

    二、闭包函数

    闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。

    闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。

    def outter(x):    x = 1    def inner():        print(x)    return inner #返回的是函数名(函数对象)f = outter(2)f()  # 1f()  # 1f()  # 1# 查看闭包的元素print(f.__closure__[0].cell_contents)  # 1

    闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。

    应用领域:

    延迟计算(原来我们是传参,现在我们是包起来)、爬虫领域。

    import requestsdef outter(url):    def get():        response = requests.get(url)        print(f"done: {url}")    return getbaidu = outter('https://www.baidu.com')python = outter('https://www.python.org')baidu()baidu()python()python()

    三、函数装饰器

    装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能。装饰器的实现必须遵循两大原则:

    • 不修改被装饰对象的源代码

    • 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    不改变函数体代码,并且不改变函数调用方式,它本质就是一个闭包函数。

    def f1(x):    def f2():        print(x)  # 10    return f2f2 = f1()f2()  # f2()

    在不改变当前函数的情况下, 给其增加新的功能:

    def log(pr):  # 将被装饰函数传入    def wrapper():        print("**********")        return pr()  # 执行被装饰的函数    return wrapper  # 将装饰完之后的函数返回(返回的是函数名)@logdef pr():    print("我是小小洋")pr()# **********# 我是小小洋

    回调函数和返回函数的实例就是装饰器。

    四、无参装饰器

    举例:

    import timedef 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 wrapperindex = time_count(index)  # index为被装饰函数index的内存地址,即index = wrapperindex()  # wrapper()

    1、被装饰函数有返回值:

    如果原始的被装饰函数index()有返回值的时候,wrapper()函数的返回值应该和index()的返回值相同,也就是说,我们需要同步原始的index()和wrapper()方法的返回值。

    import timedef index():    print('welcome to index')    time.sleep(1)    return 123def 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 wrapperindex = time_count(index)res = index()print(f"res: {res}")  #res: 123

    2、被装饰函数需要传参:

    如果原始的被装饰函数index()方法需要传参,那么我们之前的装饰器是无法实现该功能的,由于有wrapper()=index(),所以给wrapper()方法传参即可。

    import timedef index():    print('welcome to index')    time.sleep(1)    return 123def home(name):    print(f"welcome {name} to home page")    time.sleep(1)    return namedef 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 wrapperhome = time_count(home)res = home('egon')print(f"res: {res}") #res: egon

    3、装饰器模板

    def deco(func):    def wrapper(*args,**kwargs):        res = func(*args,**kwargs)        return res    return wrapper

    4、装饰器语法糖:

    在被装饰函数正上方,并且是单独一行写上@装饰器名

    import timedef 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 nameres = home('egon')print(f"res: {res}") #res: egon

    五、带参数的装饰器

    注意无参装饰器只套两层。

    import timecurrent_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@logindef 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 f2f2 = f1(2)f3 = f2()f3()

    3、有参三层装饰器:

    在函数中嵌入装饰器

    import timecurrent_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')@Foodef 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# 函数@loggeddef f(x):   """does some math"""   return x + x * xlogged(f)

    不难发现,函数 f 被with_logging取代了,当然它的docstring,__name__就是变成了with_logging函数的信息了。好在我们有functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器里面的 func 函数中,这使得装饰器里面的 func 函数也有和原函数 foo 一样的元信息了。

    from functools import wrapsdef 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@loggeddef f(x):   """does some math"""   return x + x * x

    七、装饰器顺序

    一个函数还可以同时定义多个装饰器,比如:

    @a@b@cdef f ():    pass

    它的执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于

    f = a(b(c(f)))

    八、装饰器使用场景

    现在我们来看一下装饰器在哪些地方特别耀眼,以及使用它可以让一些事情管理起来变得更简单。

    授权(Authorization)

    装饰器能有助于检查某个人是否被授权去使用一个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

    日志(Logging)

    日志是装饰器运用的另一个亮点。这是个例子:

    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 @logitdef addition_func(x):   """Do some math."""   return x + x  result = addition_func(4)# Output: addition_func was called

    以上就是“Python命名空间、作用域和装饰器怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Python命名空间、作用域和装饰器怎么使用

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Python命名空间、作用域和装饰器怎么使用

    今天小编给大家分享一下Python命名空间、作用域和装饰器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、名称空间
    2023-06-30

    Python 作用域和命名空间

    在介绍类之前,我首先要告诉你一些Python的作用域规则。类定义对命名空间有一些巧妙的技巧,你需要知道作用域和命名空间如何工作才能完全理解正在发生的事情。顺便说一下,关于这个主题的知识对任何高级Python程序员都很有用。让我们从一些定义开
    2023-01-31

    命名空间和作用域

    一、命名空间一、命名空间的分类:1、内置命名空间——python解释器:python解释器启动就可以使用的名字存储在内置内存空间;内置的名字在启动解释器的时候就被加载进内存,如input()、print()等等。2、全局命名空间——自己写的
    2023-01-31

    Python函数命名空间和作用域是什么

    这篇文章主要介绍Python函数命名空间和作用域是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.Local作用域a = 100def func5(): b = 50 a = 99 print
    2023-06-29

    Python3命名空间和作用域是什么

    这篇文章主要讲解了“Python3命名空间和作用域是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python3命名空间和作用域是什么”吧!命名空间命名空间(Namespace)是从名称
    2023-06-02

    Python名称空间及作用域怎么用

    今天小编给大家分享一下Python名称空间及作用域怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。名称空间什么是名称空间
    2023-06-26

    Python中的命名空间、作用域以及lo

    最近一直看一本python经典教材——《Python学习手册》,因为之前都是突击学的,也没有仔细看一些经典教材,所以感觉自己的基础掌握的还不是很好,虽然网络上资源多,但我觉得还是有必要买本教材来认真的读一读,底层基础决定上层建筑嘛,基础打牢
    2023-01-31

    购买域名和空间后怎么使用

    购买域名和空间后,您可以按照以下步骤使用:1. 配置域名解析:将域名解析到您购买的空间上,这样访问域名时才能访问到您的网站。2. 安装网站程序:根据您的需求选择适合的网站程序,如WordPress、Joomla等,并按照程序的安装说明进行安
    2023-06-12

    解读Python编程中的命名空间与作用域

    变量是拥有匹配对象的名字(标识符)。命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。 一个Python表达式可以访问局部命名空间和全局命名空间里的变量。如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。
    2022-06-04

    Python命名空间与作用域深入全面详解

    命名空间是从名称到对象的映射,大部分的命名空间都是通过Python字典来实现的,作用域就是一个可以直接访问命名空间的正文区域。程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的
    2022-11-13

    php命名空间怎么使用

    在PHP中,命名空间用来解决不同类或函数同名的问题,使其具有唯一性和可管理性。通过使用命名空间,可以将相关的类、函数和常量组织在一起,避免命名冲突。使用命名空间的基本语法是在文件的开头使用`namespace`关键字来定义命名空间,然后在使
    2023-08-08

    C#命名空间怎么定义和使用

    在C#中,命名空间用于组织和管理代码,以便更好地组织项目结构和避免命名冲突。要定义一个命名空间,可以使用关键字"namespace",如下所示:namespace MyNamespace{// 在这里定义类、方法等}要在代码中使用命名
    C#命名空间怎么定义和使用
    2024-03-01

    python装饰器property和setter怎么使用

    本篇内容介绍了“python装饰器property和setter怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.引子:函数也是对象
    2023-07-02

    Python中怎么使用装饰器装饰函数

    这篇文章将为大家详细讲解有关Python中怎么使用装饰器装饰函数,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。***个函数deco是装饰函数,它的参数就是被装饰的函数对象。我们可以在deco
    2023-06-17

    C#命名空间和程序集怎么使用

    这篇文章主要介绍“C#命名空间和程序集怎么使用”,在日常操作中,相信很多人在C#命名空间和程序集怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#命名空间和程序集怎么使用”的疑惑有所帮助!接下来,请跟
    2023-06-17

    租用域名主机空间怎么使用

    租用域名主机空间后,您可以使用以下步骤来使用它:1. 配置域名:将您的域名指向您的主机空间,以便您的网站可以在该空间上运行。2. 登录控制面板:使用提供的登录信息登录您的主机控制面板。3. 上传网站文件:将您的网站文件上传到主机空间中,以便
    2023-06-07

    Vuex命名空间namespaced怎么使用

    这篇文章主要介绍“Vuex命名空间namespaced怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vuex命名空间namespaced怎么使用”文章能帮助大家解决问题。在项目中,如果需要用
    2023-07-05

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录