Python全栈之作用域和闭包

目录
  • 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关键字来修改全局变量
"""

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/f3ab3fd8502e43eebd473306c0e28633.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原则(就近找变量原则)
#找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间      (内建作用域)
G —— Global(module); 函数外部所在的命名空间        (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域            (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
"""

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()

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,"word":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))
"""
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(k,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)

相关推荐

  • Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作示例

    本文实例讲述了Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作.分享给大家供大家参考,具体如下: 实例对象也可以实现闭包的功能,不过实例对象消耗的资源(内存)比闭包多. demo.py(闭包): # 闭包,分割作用域. 外层函数内部嵌套内部函数,外层函数分割变量作用域,并返回内部函数的引用. # 外层函数负责分割作用域,内层函数才是闭包提供的功能. 外层函数返回内层函数的引用,供外部使用. def my_line(k, b): # k,b只在my_line函数以及creat

  • 详解Python循环作用域与闭包

    前言 首先来看一段代码 x_list = [i for i in range(30)] y_list = [i for i in range(10, 20)] for y in y_list: x_list = filter(lambda a: a != y, x_list) x_list = list(x_list) print(x_list) print(len(x_list)) 这段代码会输出什么呢? 正确答案是一个长度为29的List. [0, 1, 2, 3, 4, 5, 6, 7,

  • 基于Python函数的作用域规则和闭包(详解)

    作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器退出.内置命名实际上存在于一个叫__builtins__的模块中,可以通过globals()['__builtins__'].__dict__查看其中的内置函数和内置异常. 全局命名空间,在读入函数所在的模块时创建,通常情况下,模块命名空间也会一直保存到解释器退出.可以通过内置函数globals()

  • 浅谈Python中的作用域规则和闭包

    在对Python中的闭包进行简单分析之前,我们先了解一下Python中的作用域规则.关于Python中作用域的详细知识,有很多的博文都进行了介绍.这里我们先从一个简单的例子入手. Python中的作用域 假设在交互式命令行中定义如下的函数: >>> a = 1 >>> def foo(): b = 2 c = 3 print "locals: %s" % locals() return "result: %d" % (a + b

  • 基于Python闭包及其作用域详解

    关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包(closure),而这个被内部函数引用的变量则被成为自由变量 闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量 命名空间和作用域 我们把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系.在 Python 中,作用域实际上可以看做是"在当前

  • Python编程中闭包的变量作用域问题解析

    目录 闭包 闭包中的变量 闭包 ​ 在我们使用返回函数的时候,由于我们在一个函数中需要返回另一个函数,因此,我们在这个函数中就需要重新定义一个函数.而这样,就造成了我们的函数嵌套问题.外面的函数相对于里面的函数而言是外函数(outer function),而里面的我们叫他内函数(inner function). def outerFunction(): #外函数 def innerFunction(): #内函数 x = 1 return x return innerFunction #返回值是

  • Python全栈之作用域和闭包

    目录 1. return返回值 2. 全局变量_局部变量 3. 函数名的使用 4. 函数的嵌套 4.1 函数的嵌套 4.2 nonlocal的使用 5. 闭包函数的定义 6. 闭包的特点_意义 小提示: 7. 小练习 总结 1. return返回值 # ### return 自定义函数的返回值 """ 概念:return 把函数内部的数据返回到函数的外面,返回到函数的调用处 1.return + 六大标准数据类型 , 除此之外还可以返回函数 或者 是类对象 2.return

  • python全栈要学什么 python全栈学习路线

    IT行业,技术要比学历.年龄.从业经验更为重要,技术水平直接决定就业薪资,想要学好python,首先要先了解精通Python语言基础.Python web开发.Python爬虫.Python数据分析这四大方面. 全栈即指的是全栈工程师,指掌握多种技能,并能利用多种技能独立完成产品的人.就是与这项技能有关的都会,都能够独立的完成. 全栈只是个概念,也分很多种类.真正的全栈工程师涵盖了web开发.DBA .爬虫 .测试.运维,要学的内容那是相当的巨量.就web开发方向而言需要学习的内容:前端知识 包

  • python全栈知识点总结

    全栈即指的是全栈工程师,指掌握多种技能,并能利用多种技能独立完成产品的人.就是与这项技能有关的都会,都能够独立的完成. 全栈只是个概念,也分很多种类.真正的全栈工程师涵盖了web开发.DBA .爬虫 .测试.运维,要学的内容那是相当的巨量.就web开发方向而言需要学习的内容:前端知识 包括HTML5 CSS3 JS Jquery Ajax,后端至少需要能够熟练使用Django和tornado,当然会flask更好. 扩展资料: 全栈工程师的厉害之处并不是他掌握很多知识,可以一个人干多份工作.而是

  • python全栈开发语法总结

    太多的小伙伴正在学习Python,就说自己以后要做全栈开发,大家知道这是做什么的吗?我们现在所知道的知识点,哪些是以后你要从事这个全栈所需要的呢?从名字上我们可以获知,"全"一样是掌握全部内容,没错,这里就是要自己掌握全部编程技能,足够独立开发的人,因此全栈士不如也说叫"全战士",如果想做,那就看下面能用到的语法吧. 1.中文编码-UTF8字符集 #!/usr/bin/env python # coding:utf8 2.数值 a = 1 b = 2.1 print

  • Python全栈之学习JS(1)

    目录 1. js的数据类型 1.1 js引入方式 1.2 注释变量 1.3 数据类型 2. js类型转换_运算符 2.1 强制转换_Number 2.2 强制转换_String 2.3 强制转换_Boolean 2.4 自动类型转换_Number_Boolean_String三者之间转换 2.5 js运算符 3. js流程控制 3.1 分支结构 3.2 分支结构_switch_case 3.3 循环结构 4. js函数 4.1 函数 4.2 函数的调用 总结 1. js的数据类型 1.1 js引

  • Python全栈之递归函数

    目录 1. 递归函数 2. 递归练习 3. 小练习 总结 1. 递归函数 # ### 递归函数 """ 递归函数 : 自己调用自己的函数 , 叫做递归函数 递 : 去 归 : 回 一去一回叫做递归 """ def digui(n): print(n,"<==1==>") if n > 0: digui(n-1) print(n,"<==2==>") digui(5) "

  • Python全栈之运算符详解

    目录 1. 算数_比较_赋值_成员 1.1 算数运算符 1.2 比较运算符 1.3 赋值运算符 1.4 成员运算符 2. 身份运算符 小提示: 3. 逻辑运算符 3.1 位运算符 3.2 小总结 4. 代码块_单项_双项分支 4.1 代码块 4.2 流程控制 4.3 单项分支 4.4 双项分支 5. 小作业 总结 1. 算数_比较_赋值_成员 1.1 算数运算符 算数运算符: + - * / // % ** # + var1 = 7 var2 = 90 res = var1 + var2 pri

  • Python全栈之列表数据类型详解

    前言 列表(list)同字符串一样都是有序的,因为他们都可以通过切片和索引进行数据访问,且列表是可变的. 创建列表的几种方法 第一种 name_list = ['Python', 'PHP', 'JAVA'] 第二种 name_list = list(['Python', 'PHP', 'JAVA']) 创建一个空列表 >>> li = list() >>> type(li) <class 'list'> 把一个字符串转换成一个列表 >>>

  • Python全栈之面向对象基础

    目录 1. 面向对象oop了解 2. 对象的相关操作 小提示: 3. 类的相关操作 4. 类对象的删除操作 小提示: 5. 小练习 小提示: 答案: 总结 1. 面向对象oop了解 # ### oop 面向对象的程序开发 # (1) 类的定义 # 1 class Car: pass # 2 推荐 class Car(): pass # 3. class Car(object): pass # (2)类的实例化 class Car(): pass obj = Car() print(obj) #

  • Python全栈之单项循环

    目录 1. 多项_巢状分支 2. 循环结构 2.1 循环结构 2.2 单项循环的练习 3. 字符串的切片 4. 小练习 问题: 答案: 总结 1. 多项_巢状分支 2. 循环结构 2.1 循环结构 2.2 单项循环的练习 3. 字符串的切片 4. 小练习 问题: 答案: 总结 1. 多项_巢状分支 多项分支 (多选一) """ if 条件表达式1: code1 elif 条件表达式2: code2 elif 条件表达式3: code3 else: `code4 如果条件表达式

随机推荐