开发者

Python全栈之作用域和闭包

开发者 https://www.devze.com 2022-12-06 09:36 出处:网络 作者: 熬夜泡枸杞
目录1. return返回值2. 全局变量_局部变量3. 函数名的使用4. 函数的嵌套4.1 函数的嵌套4.2 nonlocal的使用5. 闭包函数的定义6. 闭包的特点_意义小提示:7. 小练习总结1. return返回值
目录
  • 1. return返回值
  • 2. 全局变量_局部变量
  • 3. 函数名的使用
  • 4. 函数的嵌套
    • 4.1 函数的嵌套
    • 4.2 nonlocal的使用
  • 5. 闭包函数的定义
    • 6. 闭包的特点_意义
      • 小提示:
    • 7. 小练习
      • 总结

        1. return返回值

        # ### return 自定义函数的返回值
        """
        概念:return 把函数内部的数据返回到函数的外面,返回到函数的调用处
        1.return + 六大标准数据类型 , 除此之外还可以返回函数 或者 是类对象
        2.return 在执行时,意味着终止函数,后面的代码不执行.
        3.如果不定义return返回值,默认返回None
        """
        # (1) return + 六大标准数据类型
        def func():
        	# return 111
        	# return 6.89
        	# return "你好帅啊,我爱死你乐"
        	# return [1,2,3]
        	# return {"a":1,"b":2}
        	return 1,2,3 # 返回元组
        res = func()
        print(res)
        # (2) return 在执行时,意味着终止函数,后面的代码不执行.
        def func():
        	print(1)
        	print(2)
        	return 3
        	print(4)
        res = func()
        print(res)
        def func():
        	for i in range(5):
        		if i == 3:
        			return 4
        		print(i)
        res = func()
        print(res)
        # (3) 如果不定义return返回值,默认返回None
        def func():
        	pass
        res = func()
        print(res) # None
        # 注意点 打印的数据和返回的数据不是等价的,返回的数据是可以自定义的;
        res = print(1234)
        print(res)  # None
        
        # 模拟+-*/计算器
        """
        功能:   完成计算
        参数:   2个数字和运算符
        返回值: 计算后的结果
        """
        def calc(num1,num2,sign):
        	if sign == "+":
        		return num1 + num2
        	elif sign == "-":
        		return num1 - num2
        	elif sign == "*":
        		return num1 * num2
        	elif sign == "/":
        		if num2 == 0:
        			return "除数不能为零"
        		return num1 / num2
        	else:
        		return "抱歉,超出了我的运算范围."
        res = calc(3,5,"+")
        res = calc(3,5,"-")
        res = calc(3,5,"*")
        res = calc(3,0,"/")
        res = calc(3,0,"&")
        print(res)
        

        2. 全局变量_局部变量

        # ### 全局变量和局部变量
        """
        1.概念
        	局部变量:在函数内部定义的变量就是局部变量
        	全局变量:在函数外部定义的变量或者在函数内部使用global关键字声明是全局变量
        2.作用域:
        	局部变量的作用范围仅仅在函数的内部
        	全局变量的作用范围横跨整个文件
        3.生命周期:该变量的作用时长
        	内置命名空间 -> 全局命名空间  -> 局部命名空间 (开辟空间顺序)
        	内置属性 > 全局属性 > 局部属性 (作用时长:长->短)
        """
        # 1 局部变量
        def func():
        	# 定义一个局部变量
        	a = 1
        	# 获取当前的局部变量
        	print(a)
        	# 修改一个局部变量
        	a = 2
        	print(a)
        func()
        # print(a) error
        # 2.全局变量
        # 定义一个全局变量
        b = 10
        # 获取当前的全局变量
        print(b)
        # 修改一个全局变量
        b = 20
        print(b)
        def func():
        	print(b)
        func()
        # 3.函数内部定义全局变量
        def func():
        	global c
        	c =30
        func()
        print(c)
        # 4.函数内部修改全局变量
        d = 50
        def func():
        	global d
        	d = 51
        func()
        print(d)
        """
        总结:global的使用
        如果当前不存在全局变量,可以在函数内部通过global关键字来定义全局变量
        如果当前存在全局变量,可以在函数内部通过global关键字来修改全局变量
        """
        

        Python全栈之作用域和闭包

        3. 函数名的使用

        # ### 函数名的使用
        """
        # python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限
        """
        def func():
        	print( "我是func函数")
        # (1)动态创建
        a = 1
        print(a)
        a = func
        a()
        # (2)动态销毁
        del a
        # a()
        # func()
        # (3)当参数传递
        def func2():
        	return "我是func2函数"
        def func1(f):
        	return f() # "我是func2函数"
        res = func1(func2)
        print(res)
        # (4)作为值返回
        def func3():
        	print( "我是func3函数" )
        def func4(f):
        	return f
        res = func4(func3)	
        print(res)
        res()
        print("<===>")
        # (5)函数名可以作为容器类型数据的元素
        lst = [func,func3]
        for i in lst:
        	i()
        print("<=========>")
        # ### __doc__ 或者help查看文档
        def big_chang_cishen(something):
        	"""
        	功能: 教你怎么吃大肠
        	参数: 吃的内容
        	返回值: 是否满意
        	"""
        	print("把{}洗一洗".format(something))
        	print("直接找肠子头,放嘴里,吸一下")
        	print("擦擦嘴,满意的放下肠子头")
        	return "吃完了,真好吃~"
        big_chang_cishen("生肠子")
        # 方法一
        res = big_chang_cishen.__doc__
        print(res)
        # 方法二
        help(big_chang_cishen)
        

        4. 函数的嵌套

        4.1 函数的嵌套

        # ### 函数的嵌套
        """
        互相嵌套的两个函数![请添加图片描述](https://img-blog.csdnimg.cn/f3ab3fd8502e43eebd473306c0http://www.cppcns.come28633.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA54as5aSc5rOh5p645p2e,size_20,color_FFFFFF,t_70,g_se,x_16)
        :
        	包裹在外层的叫做外函数,内层的就是内函数
        """
        def outer():
        	# inner()
        	def inner():
        		print("我是inner函数")
        """"""
        # (1)内部函数可以直接在函数外部调用么 不行
        # inner()
        # (2)调用外部函数后,内部函数可以在函数外部调用吗 不行
        # outer()
        # inner()
        # (3)内部函数可以在函数内部调用吗 可以
        outer()
        # (4)内部函数在函数内部调用时,是否有先后顺序 有的
        # 先定义在调用
        # 在其他语言中有预加载的机制,提前把函数驻留到内存中,然后再去编译脚本内容
        # python没有预加载函数的机制,只能先定义在调用;
        
        # 外函数是outer  中间函数是inner  最里层是smaller ,调用smaller函数
        def outer():
        	def inner():
        		def smaller():
        			print("我是smaller函数")
        		smaller()
        	inner()
        outer()
        
        # LEGB 原则
        def outer():	
        	def inner():
        		def smaller():	
        			print(a)
        		smaller()
        	inner()
        outer()
        """
        LEGB原则(就近找变量原则)
        #找寻http://www.cppcns.com变量的调用顺序采用LEGB原则(即就近原则)
        B —— Builtin(Python);Python内置模块的命名空间      (内建作用域)
        G —— Global(module); 函数外部所在的命名空间        (全局作用域)
        E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
        L —— Local(function);当前函数内的作用域            (局部作用域)
        依据就近原则,从下往上 从里向外 依次寻找
        """
        

        Python全栈之作用域和闭包

        Python全栈之作用域和闭包

        Python全栈之作用域和闭包

        4.2 nonlocal的使用

        # ### nonlocal的使用 (用来修改局部变量)
        """
        nonlocal遵循LEGB原则
        (1) 它会找当前空间上一层的变量进行修改
        (2) 如果上一层空间没有,继续向上寻找
        (3) 如果最后找不到,直接报错
        """
        # (1)它会找当前空间上一层的变量进行修改
        def outer():
        	a = 10
        	def inner():
        		nonlocal a
        		a = 20
        		print(a)
        	inner()
        	print(a)
        outer()
        # (2)如果上一层空间没有,继续向上寻找
        def outer():
        	a = 20
        	def inner():
        		a = 15
        		def smaller():
        			nonlocal a
        			a = 30
        			print(a)
        		smaller()
        		print(a)
        	inner()
        	print(a)
        outer()
        # (3)如果最后找不到,直接报错
        """nonlocal 只能修改局部变量,"""
        """
        a = 20
        def outer():	
        	def inner():
        		def smaller():
        			nonlocal a
        			a = 30
        			print(a)
        		smaller()
        		print(a)
        	inner()
        	print(a)
        outer()
        error
        """
        
        # (4) 不通过nonlocal 是否可以修改局部变量呢?ok
        def outer():
        	lst = [1,2,3]
        	def inner():
        		lst[-1] = 3000
        	inner()
        	print(lst)
        outer()
        

        5. 闭包函数的定义

        # ### 闭包函数
        """
        互相嵌套的两个函数,如果内函数使用了外函数的局部变量
        并且外函数把内函数返回出来的过程,叫做闭包
        里面的内函数叫做闭包函数
        是不是闭包?
        	1.内函数用了外函数的那个局部变量
        	2.外函数返回内函数
        """
        # 1.基本语法形式
        def zhaoshenyang_family():
        	father = "马云"
        	def hobby():
        		print("我对钱没有一丝丝的兴趣,我不看重钱,这是我爸爸{}说的".format(father))
        	return hobby
        func = zhaoshenyang_family()
        func()
        print("<==1==>")
        tup = func.__closure__
        print(tup[0].cell_contents) # 马云
        print(tup)
        print("<==2==>")
        # 2.闭包的复杂形式
        def zhaowanli_family():
        	gege = "王思聪"
        	didi = "鞋王,高振宁"
        	money = 1000
        	def gege_hobby():
        		nonlocal money
        		money -= 500
        		print("我交朋友不在乎他有没有钱,反正都没有我有钱.我就喜欢交女朋友... 钱物还剩下{}".format(money))
        	def didi_hobby():
        		nonlocal money
        		money -= 400
        		print("家里有鞋柜,各式各样的奢侈鞋,一双大概20~30万,钱物还剩下{}".format(money))
        	def big_master():
        		return [gege_hobby,didi_hobby]
        	return big_master
        func = zhaowanli_family()
        print(func)
        lst = func()
        print(lst)
        # 获取哥哥函数
        gege = lst[0]
        gege()
        # 获取弟弟函数
        didi = lst[1]
        didi()
        # 3.使用 __closure__ , cell_contents 判定闭包
        """如果返回的元组中有数据说明是闭包,谁的生命周期被延长就打印谁"""
        tup = func.__closure__
        print(tup)
        # 先获取第一个单元格  cell_contents获取对象中的内容
        func1 = tup[0].cell_contents
        print("<11111>")
        """打印闭包函数didi_hobby中,生命周期被延长的属性"""
        print(func1.__closure__[0].cell_contents)
        func1()
        # 在获取第二个单元格  cell_contents获取对象中的内容
        func2 = tup[1].cell_contents
        print("<22222>")
        """打印闭包函数gege_hobby中,生命周期被延长的属性"""
        print(func2.__closure__[0].cell_contents)
        func2()
        

        Python全栈之作用域和闭包

        Python全栈之作用域和闭包

        Python全栈之作用域和闭包

        6. 闭包的特点_意义

        # ### 闭包特点
        """
        特点:在闭包函数中,内函数使用了外函数的局部变量,
        该变量会与内函数发生绑定,延长该变量的生命周期,
        持续到脚本执行结束.
        """
        def outer(val):
        	def inner(num):
        		return val + num
        	return inner
        func = outer(10)
        res = func(15)
        print(res)
        
        # ### 闭包的意义
        """全局变量的作用域大,容易被篡改"""
        num = 0
        def click_num():
        	global num
        	num += 1 # num = num + 1
        	print(num)
        click_num()
        click_num()
        click_num()
        num = 100
        click_num()
        click_num()
        # 改造,用闭包来实现
        """
        闭包的意义:
        	闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
        """
        def outer():
        	x = 0
        	def click_num():
        		nonlocal x
        		x += 1
        		print(x)
        	return click_num
        click_num = outer()
        click_num()
        click_num()
        click_num()
        x = 100
        click_num()
        click_num()
        

        小提示:

        def outer():
              a = 10
              def inner():
                    a = 20
                    print(a)
               inner()
               print(a)
        outer()
        这里的输出结果是20 10,嵌套里的两个a变量互不干扰
        
        列表可以直接可以在内外函数直接传递值,修改列表
        的时候不需要使用nolocal来修改变量的值。
        闭包可以延长局部变量的周期  
        没办法在函数的内部去修改一个全局变量的,必须通过一个global(跟nonlocal一个道理的)
        

        7. 小练习

        # # 1.定义函数:接收任意个参数,打印其中的最小值
        def func(*args):
        	lst = []
        	for i in args:
        		if isinstance(i , (float,int)):
        			lst.append(i)
        	print(lst)
        	return lst[0]
        res = func(-100,1,2,423,"sdf")
        print(res)
        # 2.定义函数:传入一个参数n,返回n的阶乘(5! = 5*4*3*2*1)
        def func(n):
        	total = 1
        	for i in range(n,0,-1):
        		total *= i
        	return total
        print(func(5))
        # 3.写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等)
        # # 将容器中的每个元素依次添加到新的列表中返回
        #例:传入函数两个参数[1,2,3] (22,33)最终args为(1,2,3,22,33)
        # 方法一
        def func(*args):
        	lst =[]
        	for i in args:
        		for j in i:
        			lst.append(j)
        	return lst
        res = func([1,2,3],(5,6,7),"abc")
        print(res)
        # 方法二
        def func(*args):
        	return list(args)
        res = func(*[1,2,3],*(5,6,7),*"abc")
        print(res)
        
        # 4.写函数,用户传入要修改的文件名,与要修改的内容,执行函数,修改操作
        # 方法一
        def func(filename,str1,str2):
        	with open(filename,mode="r+",encoding="utf-8") as fp:
        		strvar = fp.read()
        		print(strvar)
        		res = strvar.replace(str1,str2)
        	with open(filename,mode="w+",encoding="utf-8") as fp:
        		fp.write(res)
        func("ceshi2.py","内置函数","外置函数")
        # 方法二
        def func(filename,str1,str2):
        	with open(filename,mode="r+",encoding="utf-8") as fp:
        		strvar = fp.read()
        		res = strvar.replace(str1,str2)
        		# print(fp.tell())
        		fp.seek(0)
        		# 清空
        		fp.truncate()
        		fp.write(res)
        func("ceshi2.py","外置函数","内置函数")
        
        # 5.写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数
        # 方法一
        def func(strvar):
        	dic = {"num":0,"wordLWjEQFzI":0,"space":0,"other":0}
        	for i in strvar:
        		if i.isdecimal():
        			dic["num"] += 1 # dic["num"] = dic["num"] + 1
        		elif i.encode().isalpha():
        			dic["word"] += 1
        		elif i.isspace():
        			dic["space"] += 1
        		else:
        			dic["other"] += 1
        	return dic
        
        # strvar = input("请输入字符串")
        # print(func(strvar))
        LWjEQFzI"""
        print("你".isalpha())
        # 中文 => False
        print("你".encode().isalpha())
        # 字母 => True
        print("a".encode().isalpha())
        """
        # 方法二
        def func(strvar):
        	dic = {"num":0,"word":0,"space":0,"other":0}
        	lst = []
        	for i in range(97,123):
        		lst.append(chr(i))
        		lst.append(chr(i-32))
        	for i in strvar:
        		if i in "0123456789":
        			dic["num"] += 1
        		elif i in lst:
        			dic["word"] += 1
        		elif i == " ":
        			dic["space"] += 1
        		else :
        			dic["other"] += 1
        	return dic
        # strvar = input("请输入字符串")
        # print(func(strvar))
        # 6.写函数,检查字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,返回处理后的结果.
        	#例:参数为:dic = {"k1": "v1v1", "k2": [11,22,33,44]}
        def func(dic):
        	if isinstance(dic,dict):
        		for k,v in dic.items():
        			print(http://www.cppcns.comk,v)
        			dic[k] = v[:2]
        		return dic
        	else:
        		return "不是字典"
        dic = {"k1": "v1v1", "k2": [11,22,33,44]}
        print(func(dic))
        print(func([1,23,42,34,23,4234]))
        
        # 7传入多个容器类型数据,计算所有元素的个数
        def func(*args):
        	total = 0 
        	for i in args:
        		print(i)
        		total += len(i)
        	return total
        res = func("123",[5,6,7],("你好","123423"))
        print(res)
        # 改造,不去判断字符串本身的长度
        def func(*args):
        	total = 0 
        	for i in args:
        		print(i)
        		if isinstance(i,str):
        			total += 1
        		elif isinstance(i,(tuple,list,set,dict)):
        			total += len(i)
        	return total
        res = func("123",[5,6,7],("你好","123423"))
        print(res)
        

        总结

        本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号