欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python全棧之作用域和閉包

 更新時(shí)間:2021年12月01日 16:01:10   作者:熬夜泡枸杞  
這篇文章主要為大家介紹了Python作用域和閉包,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

1. return返回值

# ### return 自定義函數(shù)的返回值
"""
概念:return 把函數(shù)內(nèi)部的數(shù)據(jù)返回到函數(shù)的外面,返回到函數(shù)的調(diào)用處
1.return + 六大標(biāo)準(zhǔn)數(shù)據(jù)類(lèi)型 , 除此之外還可以返回函數(shù) 或者 是類(lèi)對(duì)象
2.return 在執(zhí)行時(shí),意味著終止函數(shù),后面的代碼不執(zhí)行.
3.如果不定義return返回值,默認(rèn)返回None
"""
# (1) return + 六大標(biāo)準(zhǔn)數(shù)據(jù)類(lèi)型
def func():
	# return 111
	# return 6.89
	# return "你好帥啊,我愛(ài)死你樂(lè)"
	# return [1,2,3]
	# return {"a":1,"b":2}
	return 1,2,3 # 返回元組
res = func()
print(res)
# (2) return 在執(zhí)行時(shí),意味著終止函數(shù),后面的代碼不執(zhí)行.
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返回值,默認(rèn)返回None
def func():
	pass
res = func()
print(res) # None
# 注意點(diǎn) 打印的數(shù)據(jù)和返回的數(shù)據(jù)不是等價(jià)的,返回的數(shù)據(jù)是可以自定義的;
res = print(1234)
print(res)  # None

# 模擬+-*/計(jì)算器
"""
功能:   完成計(jì)算
參數(shù):   2個(gè)數(shù)字和運(yùn)算符
返回值: 計(jì)算后的結(jié)果
"""
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 "除數(shù)不能為零"
		return num1 / num2
	else:
		return "抱歉,超出了我的運(yùn)算范圍."
res = calc(3,5,"+")
res = calc(3,5,"-")
res = calc(3,5,"*")
res = calc(3,0,"/")
res = calc(3,0,"&")
print(res)

2. 全局變量_局部變量

# ### 全局變量和局部變量
"""
1.概念
	局部變量:在函數(shù)內(nèi)部定義的變量就是局部變量
	全局變量:在函數(shù)外部定義的變量或者在函數(shù)內(nèi)部使用global關(guān)鍵字聲明是全局變量
2.作用域:
	局部變量的作用范圍僅僅在函數(shù)的內(nèi)部
	全局變量的作用范圍橫跨整個(gè)文件
3.生命周期:該變量的作用時(shí)長(zhǎng)
	內(nèi)置命名空間 -> 全局命名空間  -> 局部命名空間 (開(kāi)辟空間順序)
	內(nèi)置屬性 > 全局屬性 > 局部屬性 (作用時(shí)長(zhǎng):長(zhǎng)->短)
"""
# 1 局部變量
def func():
	# 定義一個(gè)局部變量
	a = 1
	# 獲取當(dāng)前的局部變量
	print(a)
	# 修改一個(gè)局部變量
	a = 2
	print(a)
func()
# print(a) error
# 2.全局變量
# 定義一個(gè)全局變量
b = 10
# 獲取當(dāng)前的全局變量
print(b)
# 修改一個(gè)全局變量
b = 20
print(b)
def func():
	print(b)
func()
# 3.函數(shù)內(nèi)部定義全局變量
def func():
	global c
	c =30
func()
print(c)
# 4.函數(shù)內(nèi)部修改全局變量
d = 50
def func():
	global d
	d = 51
func()
print(d)
"""
總結(jié):global的使用
如果當(dāng)前不存在全局變量,可以在函數(shù)內(nèi)部通過(guò)global關(guān)鍵字來(lái)定義全局變量
如果當(dāng)前存在全局變量,可以在函數(shù)內(nèi)部通過(guò)global關(guān)鍵字來(lái)修改全局變量
"""

3. 函數(shù)名的使用

# ### 函數(shù)名的使用
"""
# python中的函數(shù)可以像變量一樣,動(dòng)態(tài)創(chuàng)建,銷(xiāo)毀,當(dāng)參數(shù)傳遞,作為值返回,叫第一類(lèi)對(duì)象.其他語(yǔ)言功能有限
"""
def func():
	print( "我是func函數(shù)")
# (1)動(dòng)態(tài)創(chuàng)建
a = 1
print(a)
a = func
a()
# (2)動(dòng)態(tài)銷(xiāo)毀
del a
# a()
# func()
# (3)當(dāng)參數(shù)傳遞
def func2():
	return "我是func2函數(shù)"
def func1(f):
	return f() # "我是func2函數(shù)"
res = func1(func2)
print(res)
# (4)作為值返回
def func3():
	print( "我是func3函數(shù)" )
def func4(f):
	return f
res = func4(func3)	
print(res)
res()
print("<===>")
# (5)函數(shù)名可以作為容器類(lèi)型數(shù)據(jù)的元素
lst = [func,func3]
for i in lst:
	i()
print("<=========>")
# ### __doc__ 或者h(yuǎn)elp查看文檔
def big_chang_cishen(something):
	"""
	功能: 教你怎么吃大腸
	參數(shù): 吃的內(nèi)容
	返回值: 是否滿(mǎn)意
	"""
	print("把{}洗一洗".format(something))
	print("直接找腸子頭,放嘴里,吸一下")
	print("擦擦嘴,滿(mǎn)意的放下腸子頭")
	return "吃完了,真好吃~"
big_chang_cishen("生腸子")
# 方法一
res = big_chang_cishen.__doc__
print(res)
# 方法二
help(big_chang_cishen)

4. 函數(shù)的嵌套

4.1 函數(shù)的嵌套

# ### 函數(shù)的嵌套
"""
互相嵌套的兩個(gè)函數(shù)![請(qǐng)?zhí)砑訄D片描述](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)
:
	包裹在外層的叫做外函數(shù),內(nèi)層的就是內(nèi)函數(shù)
"""
def outer():
	# inner()
	def inner():
		print("我是inner函數(shù)")
""""""
# (1)內(nèi)部函數(shù)可以直接在函數(shù)外部調(diào)用么 不行
# inner()
# (2)調(diào)用外部函數(shù)后,內(nèi)部函數(shù)可以在函數(shù)外部調(diào)用嗎 不行
# outer()
# inner()
# (3)內(nèi)部函數(shù)可以在函數(shù)內(nèi)部調(diào)用嗎 可以
outer()
# (4)內(nèi)部函數(shù)在函數(shù)內(nèi)部調(diào)用時(shí),是否有先后順序 有的
# 先定義在調(diào)用
# 在其他語(yǔ)言中有預(yù)加載的機(jī)制,提前把函數(shù)駐留到內(nèi)存中,然后再去編譯腳本內(nèi)容
# python沒(méi)有預(yù)加載函數(shù)的機(jī)制,只能先定義在調(diào)用;

# 外函數(shù)是outer  中間函數(shù)是inner  最里層是smaller ,調(diào)用smaller函數(shù)
def outer():
	def inner():
		def smaller():
			print("我是smaller函數(shù)")
		smaller()
	inner()
outer()

# LEGB 原則
def outer():	
	def inner():
		def smaller():	
			print(a)
		smaller()
	inner()
outer()
"""
LEGB原則(就近找變量原則)
#找尋變量的調(diào)用順序采用LEGB原則(即就近原則)
B —— Builtin(Python);Python內(nèi)置模塊的命名空間      (內(nèi)建作用域)
G —— Global(module); 函數(shù)外部所在的命名空間        (全局作用域)
E —— Enclosing function locals;外部嵌套函數(shù)的作用域(嵌套作用域)
L —— Local(function);當(dāng)前函數(shù)內(nèi)的作用域            (局部作用域)
依據(jù)就近原則,從下往上 從里向外 依次尋找
"""



4.2 nonlocal的使用

# ### nonlocal的使用 (用來(lái)修改局部變量)
"""
nonlocal遵循LEGB原則
(1) 它會(huì)找當(dāng)前空間上一層的變量進(jìn)行修改
(2) 如果上一層空間沒(méi)有,繼續(xù)向上尋找
(3) 如果最后找不到,直接報(bào)錯(cuò)
"""
# (1)它會(huì)找當(dāng)前空間上一層的變量進(jìn)行修改
def outer():
	a = 10
	def inner():
		nonlocal a
		a = 20
		print(a)
	inner()
	print(a)
outer()
# (2)如果上一層空間沒(méi)有,繼續(xù)向上尋找
def outer():
	a = 20
	def inner():
		a = 15
		def smaller():
			nonlocal a
			a = 30
			print(a)
		smaller()
		print(a)
	inner()
	print(a)
outer()
# (3)如果最后找不到,直接報(bào)錯(cuò)
"""nonlocal 只能修改局部變量,"""
"""
a = 20
def outer():	
	def inner():
		def smaller():
			nonlocal a
			a = 30
			print(a)
		smaller()
		print(a)
	inner()
	print(a)
outer()
error
"""

# (4) 不通過(guò)nonlocal 是否可以修改局部變量呢?ok
def outer():
	lst = [1,2,3]
	def inner():
		lst[-1] = 3000
	inner()
	print(lst)
outer()

5. 閉包函數(shù)的定義

# ### 閉包函數(shù)
"""
互相嵌套的兩個(gè)函數(shù),如果內(nèi)函數(shù)使用了外函數(shù)的局部變量
并且外函數(shù)把內(nèi)函數(shù)返回出來(lái)的過(guò)程,叫做閉包
里面的內(nèi)函數(shù)叫做閉包函數(shù)
是不是閉包?
	1.內(nèi)函數(shù)用了外函數(shù)的那個(gè)局部變量
	2.外函數(shù)返回內(nèi)函數(shù)
"""
# 1.基本語(yǔ)法形式
def zhaoshenyang_family():
	father = "馬云"
	def hobby():
		print("我對(duì)錢(qián)沒(méi)有一絲絲的興趣,我不看重錢(qián),這是我爸爸{}說(shuō)的".format(father))
	return hobby
func = zhaoshenyang_family()
func()
print("<==1==>")
tup = func.__closure__
print(tup[0].cell_contents) # 馬云
print(tup)
print("<==2==>")
# 2.閉包的復(fù)雜形式
def zhaowanli_family():
	gege = "王思聰"
	didi = "鞋王,高振寧"
	money = 1000
	def gege_hobby():
		nonlocal money
		money -= 500
		print("我交朋友不在乎他有沒(méi)有錢(qián),反正都沒(méi)有我有錢(qián).我就喜歡交女朋友... 錢(qián)物還剩下{}".format(money))
	def didi_hobby():
		nonlocal money
		money -= 400
		print("家里有鞋柜,各式各樣的奢侈鞋,一雙大概20~30萬(wàn),錢(qián)物還剩下{}".format(money))
	def big_master():
		return [gege_hobby,didi_hobby]
	return big_master
func = zhaowanli_family()
print(func)
lst = func()
print(lst)
# 獲取哥哥函數(shù)
gege = lst[0]
gege()
# 獲取弟弟函數(shù)
didi = lst[1]
didi()
# 3.使用 __closure__ , cell_contents 判定閉包
"""如果返回的元組中有數(shù)據(jù)說(shuō)明是閉包,誰(shuí)的生命周期被延長(zhǎng)就打印誰(shuí)"""
tup = func.__closure__
print(tup)
# 先獲取第一個(gè)單元格  cell_contents獲取對(duì)象中的內(nèi)容
func1 = tup[0].cell_contents
print("<11111>")
"""打印閉包函數(shù)didi_hobby中,生命周期被延長(zhǎng)的屬性"""
print(func1.__closure__[0].cell_contents)
func1()
# 在獲取第二個(gè)單元格  cell_contents獲取對(duì)象中的內(nèi)容
func2 = tup[1].cell_contents
print("<22222>")
"""打印閉包函數(shù)gege_hobby中,生命周期被延長(zhǎng)的屬性"""
print(func2.__closure__[0].cell_contents)
func2()



6. 閉包的特點(diǎn)_意義

# ### 閉包特點(diǎn)
"""
特點(diǎn):在閉包函數(shù)中,內(nèi)函數(shù)使用了外函數(shù)的局部變量,
該變量會(huì)與內(nèi)函數(shù)發(fā)生綁定,延長(zhǎng)該變量的生命周期,
持續(xù)到腳本執(zhí)行結(jié)束.
"""
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()
# 改造,用閉包來(lái)實(shí)現(xiàn)
"""
閉包的意義:
	閉包可以?xún)?yōu)先使用外函數(shù)中的變量,并對(duì)閉包中的值起到了封裝保護(hù)的作用.外部無(wú)法訪問(wèn).
"""
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()
這里的輸出結(jié)果是20 10,嵌套里的兩個(gè)a變量互不干擾

列表可以直接可以在內(nèi)外函數(shù)直接傳遞值,修改列表
的時(shí)候不需要使用nolocal來(lái)修改變量的值。
閉包可以延長(zhǎng)局部變量的周期  
沒(méi)辦法在函數(shù)的內(nèi)部去修改一個(gè)全局變量的,必須通過(guò)一個(gè)global(跟nonlocal一個(gè)道理的)

7. 小練習(xí)

# # 1.定義函數(shù):接收任意個(gè)參數(shù),打印其中的最小值
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.定義函數(shù):傳入一個(gè)參數(shù)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.寫(xiě)函數(shù),傳入函數(shù)中多個(gè)實(shí)參(均為可迭代對(duì)象如字符串,列表,元祖,集合等)
# # 將容器中的每個(gè)元素依次添加到新的列表中返回
#例:傳入函數(shù)兩個(gè)參數(shù)[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.寫(xiě)函數(shù),用戶(hù)傳入要修改的文件名,與要修改的內(nèi)容,執(zhí)行函數(shù),修改操作
# 方法一
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","內(nèi)置函數(shù)","外置函數(shù)")
# 方法二
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","外置函數(shù)","內(nèi)置函數(shù)")

# 5.寫(xiě)函數(shù),計(jì)算傳入字符串中【數(shù)字】、【字母】、【空格] 以及 【其他】的個(gè)數(shù)
# 方法一
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("請(qǐng)輸入字符串")
# 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("請(qǐng)輸入字符串")
# print(func(strvar))
# 6.寫(xiě)函數(shù),檢查字典的每一個(gè)value的長(zhǎng)度,如果大于2,那么僅保留前兩個(gè)長(zhǎng)度的內(nèi)容,返回處理后的結(jié)果.
	#例:參數(shù)為: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傳入多個(gè)容器類(lèi)型數(shù)據(jù),計(jì)算所有元素的個(gè)數(shù)
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)
# 改造,不去判斷字符串本身的長(zhǎng)度
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)

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

最新評(píng)論