溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python全棧作用域和閉包怎么使用

發(fā)布時間:2021-12-02 16:07:26 來源:億速云 閱讀:84 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“Python全棧作用域和閉包怎么使用”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

1. return返回值

# ### return 自定義函數(shù)的返回值
"""
概念:return 把函數(shù)內(nèi)部的數(shù)據(jù)返回到函數(shù)的外面,返回到函數(shù)的調(diào)用處
1.return + 六大標(biāo)準(zhǔn)數(shù)據(jù)類型 , 除此之外還可以返回函數(shù) 或者 是類對象
2.return 在執(zhí)行時,意味著終止函數(shù),后面的代碼不執(zhí)行.
3.如果不定義return返回值,默認(rèn)返回None
"""
# (1) return + 六大標(biāo)準(zhǔn)數(shù)據(jù)類型
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 在執(zhí)行時,意味著終止函數(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
# 注意點 打印的數(shù)據(jù)和返回的數(shù)據(jù)不是等價的,返回的數(shù)據(jù)是可以自定義的;
res = print(1234)
print(res)  # None

# 模擬+-*/計算器
"""
功能:   完成計算
參數(shù):   2個數(shù)字和運(yùn)算符
返回值: 計算后的結(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)部
	全局變量的作用范圍橫跨整個文件
3.生命周期:該變量的作用時長
	內(nèi)置命名空間 -> 全局命名空間  -> 局部命名空間 (開辟空間順序)
	內(nèi)置屬性 > 全局屬性 > 局部屬性 (作用時長:長->短)
"""
# 1 局部變量
def func():
	# 定義一個局部變量
	a = 1
	# 獲取當(dāng)前的局部變量
	print(a)
	# 修改一個局部變量
	a = 2
	print(a)
func()
# print(a) error
# 2.全局變量
# 定義一個全局變量
b = 10
# 獲取當(dāng)前的全局變量
print(b)
# 修改一個全局變量
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)部通過global關(guān)鍵字來定義全局變量
如果當(dāng)前存在全局變量,可以在函數(shù)內(nèi)部通過global關(guān)鍵字來修改全局變量
"""

Python全棧作用域和閉包怎么使用

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

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

4. 函數(shù)的嵌套

4.1 函數(shù)的嵌套

# ### 函數(shù)的嵌套
"""
互相嵌套的兩個函數(shù)![請?zhí)砑訄D片描述](https://img-blog.csdnimg.cn/f3ab3fd8502e43eebd473306c0e28633.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA54as5aSc5rOh6p645p2e,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)用時,是否有先后順序 有的
# 先定義在調(diào)用
# 在其他語言中有預(yù)加載的機(jī)制,提前把函數(shù)駐留到內(nèi)存中,然后再去編譯腳本內(nèi)容
# python沒有預(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ù)就近原則,從下往上 從里向外 依次尋找
"""

Python全棧作用域和閉包怎么使用

Python全棧作用域和閉包怎么使用

Python全棧作用域和閉包怎么使用

4.2 nonlocal的使用

# ### nonlocal的使用 (用來修改局部變量)
"""
nonlocal遵循LEGB原則
(1) 它會找當(dāng)前空間上一層的變量進(jìn)行修改
(2) 如果上一層空間沒有,繼續(xù)向上尋找
(3) 如果最后找不到,直接報錯
"""
# (1)它會找當(dāng)前空間上一層的變量進(jìn)行修改
def outer():
	a = 10
	def inner():
		nonlocal a
		a = 20
		print(a)
	inner()
	print(a)
outer()
# (2)如果上一層空間沒有,繼續(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)如果最后找不到,直接報錯
"""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. 閉包函數(shù)的定義

# ### 閉包函數(shù)
"""
互相嵌套的兩個函數(shù),如果內(nèi)函數(shù)使用了外函數(shù)的局部變量
并且外函數(shù)把內(nèi)函數(shù)返回出來的過程,叫做閉包
里面的內(nèi)函數(shù)叫做閉包函數(shù)
是不是閉包?
	1.內(nèi)函數(shù)用了外函數(shù)的那個局部變量
	2.外函數(shù)返回內(nèi)函數(shù)
"""
# 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.閉包的復(fù)雜形式
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)
# 獲取哥哥函數(shù)
gege = lst[0]
gege()
# 獲取弟弟函數(shù)
didi = lst[1]
didi()
# 3.使用 __closure__ , cell_contents 判定閉包
"""如果返回的元組中有數(shù)據(jù)說明是閉包,誰的生命周期被延長就打印誰"""
tup = func.__closure__
print(tup)
# 先獲取第一個單元格  cell_contents獲取對象中的內(nèi)容
func1 = tup[0].cell_contents
print("<11111>")
"""打印閉包函數(shù)didi_hobby中,生命周期被延長的屬性"""
print(func1.__closure__[0].cell_contents)
func1()
# 在獲取第二個單元格  cell_contents獲取對象中的內(nèi)容
func2 = tup[1].cell_contents
print("<22222>")
"""打印閉包函數(shù)gege_hobby中,生命周期被延長的屬性"""
print(func2.__closure__[0].cell_contents)
func2()

Python全棧作用域和閉包怎么使用

Python全棧作用域和閉包怎么使用

Python全棧作用域和閉包怎么使用

6. 閉包的特點_意義

# ### 閉包特點
"""
特點:在閉包函數(shù)中,內(nèi)函數(shù)使用了外函數(shù)的局部變量,
該變量會與內(nèi)函數(shù)發(fā)生綁定,延長該變量的生命周期,
持續(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()
# 改造,用閉包來實現(xiàn)
"""
閉包的意義:
	閉包可以優(yōu)先使用外函數(shù)中的變量,并對閉包中的值起到了封裝保護(hù)的作用.外部無法訪問.
"""
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,嵌套里的兩個a變量互不干擾

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

7. 小練習(xí)

# # 1.定義函數(shù):接收任意個參數(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ù):傳入一個參數(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.寫函數(shù),傳入函數(shù)中多個實參(均為可迭代對象如字符串,列表,元祖,集合等)
# # 將容器中的每個元素依次添加到新的列表中返回
#例:傳入函數(shù)兩個參數(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.寫函數(shù),用戶傳入要修改的文件名,與要修改的內(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.寫函數(shù),計算傳入字符串中【數(shù)字】、【字母】、【空格] 以及 【其他】的個數(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("請輸入字符串")
# 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.寫函數(shù),檢查字典的每一個value的長度,如果大于2,那么僅保留前兩個長度的內(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傳入多個容器類型數(shù)據(jù),計算所有元素的個數(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)
# 改造,不去判斷字符串本身的長度
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)

“Python全棧作用域和閉包怎么使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI