1. 作用域

  • 作用域: 限制一个变量或一段代码可用范围,好处是提高了城乡逻辑局部性,减少名字冲突

  • 作用域结构图:
    image

    • Local(局部作用域):在函数中定义的变量,def关键字定义的语句块中,即函数中定义的变量
    • Enclosed(嵌套作用域): 一般出现在函数中嵌套一个函数时,在外部函数中的作用域称为嵌套作用域(闭包常见)
    • Global(全局作用域):文件顶层定义的变量
    • Built-in(内置作用域): 系统内解释器定义的变量,例如关键字。
  • 闭包:

    • 你可以简单粗暴地理解为闭包就是一个定义在函数内部函数,闭包使得变量即使脱离了该函数的作用域范围也依然能被访问到,像上面所说的嵌套函数也是闭包的一种形式(将内部嵌套定义的函数作为返回值)。

    • 示例:

      def outer():
      	x = 1
      	def inner():
      		print(x) # 1
      	return inner # 不加括号,表示返回函数体
      sf = outer()
      sf() # 调用,等同于outer()()
      
    • 在一个外部函数内定义了一个函数,内部函数里引用外部函数的变量,并且外部函数的返回值是内函数的引用,这样就构成了一个闭包,并且满足了闭包的三个条件:

      • 两层以上嵌套关系
    • 内部函数调用外部函数定义的变量

    • 外部函数返回内部函数体对象, 而不是函数体结果(加括号)

  • 函数装饰器

    • 函数装饰器作用:装饰器本质上是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

    • 应用场景:记录日志、性能测试、权限效验等

    • 示例:

      • 示例:无参数

        • 示例1、无参数装饰调用

          #!/usr/bin/env python
          # _*_ coding: utf-8 _*_
          # Author:shichao
          # File: .py
          
          
          # 装饰器无参数
          
          def hello():
              print("我是源函数")
          
          def hello2():
              print("我是一个求和的函数,正在执行中")
          
          def decorator(func):         # func要接收一个函数
              def f():
                  print("原函数开始执行")
                  func()
                  print("原函数执行结束")
          
              return f # 返回函数体
          
          # 把装饰器传入函数
          dec = decorator(hello)
          dec2 = decorator(hello2)
          
          # 调用内部函数
          dec()
          dec2()
          
          
        • 示例2、无参数装饰器使用“@”调用

          python提供一个更简洁引用装饰器的方法:语法糖“@”

          #!/usr/bin/env python
          # _*_ coding: utf-8 _*_
          # Author:shichao
          # File: .py
          
          
          # 装饰器: 无参数装饰器"@"
          
          
          def test_dec(func):
              def f():
                  print("test功能刚开始执行")
                  func()
                  print("test功能执行结束")
          
              return f
          @test_dec
          
          # 需要调用的装饰器,需要放到装饰器下面
          def test():
              print("我测试装饰器无参数")
          
          test()
          
      • 函数装饰:带参数

        • 示例1:装饰器带参数传递示例

          def decorator(func):
          	def f(msg):
          		print("原函数开始执行了")
          		func(msg)
          		print("原函数执行结束了")
          	return f
          
          @decorator
          def hello(msg):
          	print(msg)
            
          hello("我是原函数")
          

2. 作用域案例

  • 案例1、函数作用域与闭包

    #!/usr/bin/env python
    # _*_ coding: utf-8 _*_
    # Author:shichao
    # File: .py
    
    x = 123      # 全局作用域
    
    def outer():
        x = 456       # 嵌套作用域
        def inner():
            s = 789    # 局部作用域
            print(s)
            print(x)
        return inner()
    outer()
    
  • 案例2、函数装饰器

    #!/usr/bin/env python
    # _*_ coding: utf-8 _*_
    # Author:shichao
    # File: .py
    
    
    # 装饰器无参数
    
    def hello():
        print("我是源函数")
    
    def decorator(func):         # func要接收一个函数
        def f():
            print("原函数开始执行")
            func()
            print("原函数执行结束")
    
        return f() # 返回函数体
    
    # 把装饰器传入函数,调用内部函数
    decorator(hello)
    
  • 案例3、函数装饰器使用“@”调用装饰器

    #!/usr/bin/env python
    # _*_ coding: utf-8 _*_
    # Author:shichao
    # File: .py
    
    
    # 装饰器: 无参数装饰器"@"
    
    
    def test_dec(func):
        def f():
            print("test功能刚开始执行")
            func()
            print("test功能执行结束")
    
        return f
    @test_dec
    
    # 需要调用的装饰器,需要放到装饰器下面
    def test():
        print("我测试装饰器无参数")
    
    
    test()
    
  • 案例4、函数装饰器:带参数

    #!/usr/bin/env python
    # _*_ coding: utf-8 _*_
    # Author:shichao
    # File: .py
    
    
    def decorator(func):
        def f(*args):
            print("原函数开始执行了")
            func(*args)
            print("原函数执行结束了")
    
        return f
    
    @decorator
    def hello(*args):
        print(*args)
    
    hello("我是原函数")
    
  • 案例5、函数装饰器:使用*args和**kwargs

    #!/usr/bin/env python
    # _*_ coding: utf-8 _*_
    # Author:shichao
    # File: .py
    
    
    # 使用**kwargs
    def decorator(func):
        def f(*args,**kwargs):
            print("原函数开始执行了")
            func(*args,**kwargs)
            print("原函数执行结束了")
    
        return f
    
    @decorator
    def hello(*args, **kwargs):
        print(args,kwargs)
        print("我是一个求和函数,只在执行")
    
    hello(4,5,a=1,b=2)