作用域

程序创建, 访问, 改变一个变量时, 都是在一个保存该变量的空间内进行, 这个空间被称为命名空间, 即作用域

  • Built-in 内置

    • 可以在Python环境中的任何模块, 任意位置访问和调用
  • Global 全局变量

    • 只作用于当前模块(可以理解为当前文件)
    • 可以简单地理解为定以在函数外的变量就是全局变量, 如果在函数体定义那就时局部变量.
    • 如何将局部变量变成全局变量?

      • 使用global关键字

        a = 1
        
        def foo():
            global a
            a = 2
            print(a)
        
        foo()
        print(a)
  • Enclosed(嵌套) 自由变量

    在嵌套函数中, 访问函数体之外的非全局变量

    • 只作用于嵌套函数体
    • 最大的应用就是闭包
    • 自由变量是个相对的概念
    • 将局部变量变成自由变量

      • 使用nonlocal关键字

        def make_averager():
            total = 0
            count = 0
            def averager(value):
                nonlocal total, count
                total += value
                count += 1
                return total / count
            return averager
            
        my_avg = make_averager()
        print(my_avg(1))
        print(my_avg(2))
  • Local局部变量

    • 只作用于当前函数体
    • 一旦变量在函数体中赋值, 那么该变量相对该函数来说就是局部变量

      a = 1
      b = []
      
      
      def foo():
          a = 2
          b.append(2)
          # 局部变量会在函数声明的时候就定义好
          # 不是按照我们逻辑思维上先执行全局变量b.append(2), 然后再声明一个局部变量b
          # 而是再函数声明之初就已经定义了b为局部变量
          # b = 3
          return None
      
      foo()
      print(a)
      print(b)

闭包和装饰器

  • 闭包

    闭包指延申了作用域的函数, 也就是作用域中的Enclosed的概念

    def make_averager():
        series = []
        def averager(value):
            series.append(value)
            total = sum(series)
            return total / len(series)
        return averager
    
    # my_avg就是延申了作用域的函数
    # series就是被延申作用域的变量
    my_avg = make_averager()
    print(my_avg(1))
    print(my_avg(2))
  • 装饰器

    • 实现原理

      就是闭包, 延申了被装饰函数的作用域, 本质是将函数作为参数传递给一个可调用对象(函数或类)

    • 目的

      增加和扩展可调用对象(函数或类)的行为

    • 实现一个装饰器

      • 通过@关键字装饰函数

        def clock_it_deco(func):
            def wrapper(*args, **kwargs):
                start_time = time.time()
                result = func(*args, **kwargs)
                end_time = time.time()
                print(f"{func.__name__} execute time: {format(end_time - start_time, '.2f')} s")
                return result
            return wrapper
        
        # @other_deco
        @clock_it_deco
        def foo(a, b):
            count = 1
            while True:
                if count > a ** b:
                    break
                count += 1
        
        foo(10, 5)
      • 等同于

        foo = clock_it_deco(foo)
        foo(10, 5)
Last modification:September 2, 2022
如果觉得我的文章对你有用,请随意赞赏