目录

  • 一、函数对象
  • 1.1 函数可以被引用
  • 1.2 函数可以作为容器类型的元素
  • 1.3 函数可以作为参数传入另外一个函数
  • 1.4 函数的返回值可以是一个函数
  • 二 、闭包函数
  • 2.1 闭与包
  • 2.2 闭包函数传递参数


一、函数对象

函数对象指的是函数可以被当做’数据’来处理,具体可以分为四个方面的使用

1.1 函数可以被引用

def add(x,y):
    return x+y

func = add
func(1,2) # 结果 3

1.2 函数可以作为容器类型的元素

dic={'add':add,'max':max}

print(dic)
# {'add': <function add at 0x100661e18>, 'max': <built-in function max>}
dic['add'](1,2)  # 3

1.3 函数可以作为参数传入另外一个函数

def foo(x,y,func):
   return func(x,y)

foo(1,2,add)  # 3

1.4 函数的返回值可以是一个函数

def bar():
    return add

func=bar()
func(1,2)  # 3

二 、闭包函数

2.1 闭与包

闭函数:就是被封闭起来的函数–>定义在函数内部的函数

特点:只能在函数内部用

'warpper 就是一个闭函数 只能在 outter 函数内部用'
def outter():
  def wrapper():
    pass

包函数:某个函数 访问了一个来自 外层函数作用域 的变量,而不是全局作用域

def outter():
  x=100
  def wrapper():
    print(x)

基于函数对象的概念,可以将函数返回到任意位置去调用,但作用域的关系是在定义完函数时就已经被确定了的,与函数的调用位置无关

总结:“闭”代表函数是内部的,“包”代表函数外’包裹’着对外层作用域的引用。因而无论在何处调用闭包函数,使用的仍然是包裹在 “内嵌函数” 其外部作用域的变量

闭包函数就是:在函数内部的函数引用了一个来自于外层函数作用域中的变量

对于 wrapper 函数,理论上只能在函数内部使用,那么如何操作能够让 wrapper 函数在全局变量中也能用到呢?

"利用到函数的返回值 以及函数对象"

def outter():
  x=100
  def wrapper():
    print(x)
  return wrapper # 此时 outter 函数调用后的返回值是函数对象 wrapper

f = outter()  # 此时相当于将 函数对象 wrapper 赋值给 f
f() # 调用 f函数相当于 调用 wrapper

此时能够发现 f 是一个全局变量,wrapper 是一个函数的局部变量,但是调用 f 等同于调用了 wrapper ,所以此时无论在哪里调用 f 都可以,至此达到了无论在哪里都能调用到 wrapper.

因此无论在何处调用闭包函数,使用的仍然是包裹在其外层的变量

"函数 f2 在定义阶段时 x的值就是 1 "
x=1

def f1():
    def f2(): # step 6
        print(x)  
    return f2 # step 3

def f3():
    x=3  # step 2
    f4 = f1()   # step 4 --> f4 = f2
    f4()  #  step 5

f3() # step 1

step 1:调用 f3( )

step 2:定义了 x =3 ,

step 3:调用f1( ), f1( )的返回值为 函数对象 f2

step 4:将f1( )的返回值赋值给 f4,等同于 f4 = f2

step 5:调用 f4( ),等于调用 f2( )

step 6:调用 f2( ) 运行函数 f2 内部的代码,print( x ),在函数 f2( ) 内部没有 x, 由内部函数 f2向外寻找x ,发现外部函数函数 f1( ) 也没有 x ,再找全局变量 能够找到 x = 1,所以打印出来的 就是 1

2.2 闭包函数传递参数

'通过 outter 给闭包函数 wrapper 传递的参数 x,不是全局变量,而是 wrapper 专属的变量'
def outter(x):
  # x = 100
  def wrapper():
    print(x)
  return wrapper 

f = outter(100)  
f()