zoukankan      html  css  js  c++  java
  • 为什么要使用nonlocal

      Python3中加入了新的关键字nonlocal,当在一个嵌套的函数中对变量申明为nonlocal时,就明确表示这个变量是外部函数中定义的变量。也许会有这么一个问题:按照python的LEGB原则,在函数本地作用域找不到变量的情况下,解释器会自动在外层函数寻找,nonlocal关键字岂不是显得多余?   是的,当一个函数在本地作用域找不到变量申明时会向外层函数寻找,这在函数闭包中很常见。如下:

    1 def test(num1):
    2     def add(num2):
    3         return num1 + num2
    4     return add
    5     
    6 a = test(1)
    7 b = test(2)
    8 print(a(1))
    9 print(b(1))

    输出为:

    2
    3

    但是在本地作用域中使用的变量后,还想对此变量进行更改赋值就会报错。如下:

    def test():
        count = 1
        def add():
            print(count)
            count += 1
        return add
    
    a = test()
    a()

    输出为:

    ---------------------------------------------------------------------------
    UnboundLocalError                         Traceback (most recent call last)
    <ipython-input-6-24732f13d2b6> in <module>()
          7 
          8 a = test()
    ----> 9 a()
    
    <ipython-input-6-24732f13d2b6> in add()
          2     count = 1
          3     def add():
    ----> 4         print(count)
          5         count += 1
          6     return add
    
    UnboundLocalError: local variable 'count' referenced before assignment

    在上面代码中,如果在使用count前面加上关键字nonlocal申明就可解决这个问题:

    def add():
        count = 1
        def fun():
            nonlocal count
            print(count)
            count += 1
        return fun
    
    a = add()
    a()
    a()

    输出为:

    1
    2

      上面代码完美地解决了函数嵌套调用外部变量的问题;另外,如果从另一个角度来看我们给此函数增加了记录函数状态的功能。当然,这也可以通过申明全局变量来实现增加函数状态的功能。当这样会出现以下问题:

      1. 每次调用函数时,都得在全局作用域申明变量。别人调用函数时还得查看函数内部代码。

      2. 当函数在多个地方被调用并且同时记录着很多状态时,会造成非常地混乱。

      使用nonlocal的好处是,在为函数添加状态时不用额外地添加全局变量,因此可以大量地调用此函数并同时记录着多个函数状态,每个函数都是独立、独特的。针对此项功能其实还个一个方法,就是使用类,通过定义__call__可实现在一个实例上直接像函数一样调用。

  • 相关阅读:
    二、策略模式之商场促销计价器
    一、简单工厂模式之简易计算器
    java学习基础知识十——反射
    java学习基础知识九——IO
    java学习基础知识八——泛型
    java学习基础知识七
    java学习基础知识六
    二、机器学习模型评估
    《将博客搬至CSDN》
    一、Hadoop课程
  • 原文地址:https://www.cnblogs.com/zhouyang123200/p/6538160.html
Copyright © 2011-2022 走看看