python函数之函数对象、函数嵌套、名称空间与作用域和闭包函数

函数对象

  一、函数是第一类对象(即函数可以当作数据传递),函数是第一等公民

    #1 可以被赋值
        # def foo():  # foo->函数的内存地址

            # print('from foo')

        # f=foo  将foo的内存地址赋值给f
        # print(f)
        #f()
    #2 可以当作参数传给另一个函数
        # def foo():  # foo->函数的内存地址
          # print('from foo')
        # def func(f):
          # print(f)
        # f()
        # func(foo)
    #3 返回值可以是函数
        # def foo():  # foo->函数的内存地址

          # print('from foo')

        # def func(f):

          # return f

        # res=func(foo)

        # print(res)
    #4 可以当作容器类型的元素
        # def foo():  # foo->函数的内存地址

          # print('from foo')

        # l = [foo]

        # print(l)
  二、利用该特性,优雅的取代多分支的if
        def foo():
            print('foo')

        def bar():
            print('bar')

        dic={
            'foo':foo,
            'bar':bar,
        }
        while True:
            choice=input('>>: ').strip()
            if choice in dic:
                dic[choice]()

函数嵌套

    1、函数的嵌套调用:在调用一个函数的过程中,该函数内部又调用了其他函数
        def max(x,y):
            if x > y:
              return x  
            else:
              return y
        def max4(a,b,c,d):
            res1=max(a,b)
            res2=max(res1,c)
            res3=max(res2,d)
            return res3
        print(res)
        max4(1,2,3,4)
  2、函数的嵌套定义:在函数内又定义了其他函数-------->封闭
        def f1():
            def f2():
                def f3():
                    print('from f3')
                f3()
            f2()

        f1()

名称空间与作用域

     1、 名称空间Namespace: 存放名字与内存地址绑定关系的地方
		内置名称空间:放的是python自带的名字,print\len\input
			生命周期:解释器启动则产生,解释器关闭则销毁

		全局名称空间:放的是顶级的名字,如下x\y\foo

			生命周期:运行python文件则立即产生,python文件运行完毕则结束
		局部名称空间:放的是函数内的名字,如上z

			生命周期:调用函数则产生,函数调用完毕则销毁

		重要结论1: 名字的查找优先级
			局部-》全局-》内置
			基于自己当前所在的位置向外查找,LEGB
		重要结论2: 名称空间的嵌套关系是以函数定义为准生成的,与调用位置无关
	
   2、作用域
		1、作用域范围
			全局作用域:全局存活,全局有效

				内置名称空间,全局名称空间

			局部作用域:临时存活,局部有效

				局部名称空间
		2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
			x=1
			def f1():
				def f2():
					print(x)
				return f2
			x=100
			def f3(func):
				x=2
				func()
			x=10000
			f3(f1())

		3、查看作用域:globals(),locals()
			LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
			locals 是函数内的名字空间,包括局部变量和形参
			enclosing 外部嵌套函数的名字空间(闭包中常见)
			globals 全局变量,函数定义所在模块的名字空间
			builtins 内置模块的名字空间

global与nonlocal关键字

global关键字  将全局变量拿来局部用
	x=111
	def foo():
		global x
		x=222
	foo()
	print(x)
nonlocal关键字: 声明一个名字是来自于外层函数,如果外层没有不会找到全局,会报错
	x = 1
	def f1():
		x = 2  # 将x=2注销,在函数内找不到x,运行程序会报错
		def f2():
			nonlocal x
			x = 3
		f2()
		print(x)
	f1()

闭包函数

什么是闭包函数
	闭包函数=函数对象+函数嵌套定义+名称空间与作用域
	闭函数:定义在函数内部的函数
	包函数: 内部函数引用了一个外层函数的名字
	
	内部函数包含对外部作用域而非全局作用域的引用
	之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来
	
闭包的函数的作用:闭包函数是一种为函数体传参的方案
	为函数体传参方案一:直接使用形参
		def wrapper(x):
			print(x)
		wrapper(111)
		wrapper(222)
		 wrapper(333)
	为函数体传参方案二:闭包函数
		def outter(x):
			# x = 111  #写x=111,就把写死了
			def wrapper():
				print(x)
			return wrapper
		wrapper = outter(111)
		wrapper()
		wrapper = outter(222)
		wrapper()

闭包函数的意义与应用
	闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
	应用领域:延迟计算(原来我们是传参,现在我们是包起来)
		from urllib.request import urlopen
		def index(url):
			def get():
				return urlopen(url).read()
			return get

		baidu=index('http://www.baidu.com')
		print(baidu().decode('utf-8'))
posted @ 2021-06-30 15:09  zhutianyu  阅读(72)  评论(0)    收藏  举报