Python基础知识(第六天)
76.函數(shù)也是對(duì)象_內(nèi)存分析
函數(shù)也是對(duì)象,內(nèi)存底層分析
Python 中,“一切都是對(duì)象”。實(shí)際上,執(zhí)行 def 定義函數(shù)后,系統(tǒng)就創(chuàng)建了相應(yīng)的函數(shù)對(duì)象。我們執(zhí)行如下程序,然后進(jìn)行解釋:
def print_star(n):
print("*"*n)
print(print_star)
print(id(print_star))
c = print_star
c(3)
上面代碼執(zhí)行 def 時(shí),系統(tǒng)中會(huì)創(chuàng)建函數(shù)對(duì)象,并通過(guò) print_star 這個(gè)變量進(jìn)行引用:
我們執(zhí)行“c=print_star”后,顯然將 print_star 變量的值賦給了變量 c,內(nèi)存圖變成了:
顯然,我們可以看出變量 c?和 print_star?都是指向了同一個(gè)函數(shù)對(duì)象。因此,執(zhí)行 c(3)和執(zhí)行 print_star(3)的效果是完全一致的。Python 中,圓括號(hào)意味著調(diào)用函數(shù)。在沒(méi)有圓括號(hào)的情況下,Python?會(huì)把函數(shù)當(dāng)做普通對(duì)象。
77.變量的作用域_全局變量_局部變量_棧幀內(nèi)存分析講解
變量的作用域(全局變量和局部變量)
變量起作用的范圍稱為變量的作用域,不同作用域內(nèi)同名變量之間互不影響。變量分為:全局變量、局部變量。
全局變量:
1.在函數(shù)和類定義之外聲明的變量。作用域?yàn)槎x的模塊,從定義位置開(kāi)始直到模塊結(jié)束。
2.全局變量降低了函數(shù)的通用性和可讀性。應(yīng)盡量避免全局變量的使用。
3.全局變量一般做常量使用。
4.函數(shù)內(nèi)要改變?nèi)肿兞康闹?#xff0c;使用 global?聲明一下。
局部變量:(在棧幀里面,使用完棧幀消失)
1.在函數(shù)體中(包含形式參數(shù))聲明的變量。
2.局部變量的引用比全局變量快,優(yōu)先考慮使用。
如果局部變量和全局變量同名,則在函數(shù)內(nèi)隱藏全局變量,只使用同名的局部變量。
print(locals())? ? ??#打印輸出的局部變量
print(globals())? ? ? ? ?#打印輸出的全局變量
78.局部變量和全局變量_效率測(cè)試
局部變量和全局變量效率測(cè)試
局部變量的查詢和訪問(wèn)速度比全局變量快,優(yōu)先考慮使用,尤其是在循環(huán)的時(shí)候。在特別強(qiáng)調(diào)效率的地方或者循環(huán)次數(shù)較多的地方,可以通過(guò)將全局變量轉(zhuǎn)為局部變量提高運(yùn)行速度。
import math import time def test01():start = time.time()for i in range(10000000):math.sqrt(30)end = time.time()print("耗時(shí){0}".format((end-start)))def test02():b = math.sqrtstart = time.time()for i in range(10000000):b(30)end = time.time()print("耗時(shí){0}".format((end-start)))test01() test02()79.參數(shù)的傳遞_傳遞可變對(duì)象_內(nèi)存分析
參數(shù)的傳遞
函數(shù)的參數(shù)傳遞本質(zhì)上就是:從實(shí)參到形參的賦值操作。 Python?中“一切皆對(duì)象”, 所有的賦值操作都是“引用的賦值”。所以,Python?中參數(shù)的傳遞都是“引用傳遞”,不是“值傳遞”。具體操作時(shí)分為兩類:
1.對(duì)“可變對(duì)象”進(jìn)行“寫(xiě)操作”,直接作用于原對(duì)象本身。
2.對(duì)“不可變對(duì)象”進(jìn)行“寫(xiě)操作”,會(huì)產(chǎn)生一個(gè)新的“對(duì)象空間”,并用新的值填充這塊空間。(起到其他語(yǔ)言的“值傳遞”效果,但不是“值傳遞”)
可變對(duì)象有:字典、列表、集合、自定義的對(duì)象等
不可變對(duì)象有:數(shù)字、字符串、元組、function 等
傳遞可變對(duì)象的引用
傳遞參數(shù)是可變對(duì)象(例如:列表、字典、自定義的其他可變對(duì)象等),實(shí)際傳遞的還是對(duì)象的引用。在函數(shù)體中不創(chuàng)建新的對(duì)象拷貝,而是可以直接修改所傳遞的對(duì)象。
?
80.參數(shù)的傳遞_傳遞不可變對(duì)象_內(nèi)存分析
傳遞不可變對(duì)象的引用
傳遞參數(shù)是不可變對(duì)象(例如:int、float、字符串、元組、布爾值),實(shí)際傳遞的還是對(duì)象的引用。在”賦值操作”時(shí),由于不可變對(duì)象無(wú)法修改,系統(tǒng)會(huì)新創(chuàng)建一個(gè)對(duì)象。
?
81.淺拷貝和深拷貝_內(nèi)存分析
淺拷貝和深拷貝
為了更深入的了解參數(shù)傳遞的底層原理,我們需要講解一下“淺拷貝和深拷貝”。我們可以 ???使用內(nèi)置函數(shù):copy(淺拷貝)、deepcopy(深拷貝)。
淺拷貝:不拷貝子對(duì)象的內(nèi)容,只是拷貝子對(duì)象的引用。
深拷貝:會(huì)連子對(duì)象的內(nèi)存也全部拷貝一份,對(duì)子對(duì)象的修改不會(huì)影響源對(duì)象
??
82.參數(shù)的傳遞_不可變對(duì)象含可變子對(duì)象_內(nèi)存分析
傳遞不可變對(duì)象時(shí)。不可變對(duì)象里面包含的子對(duì)象是可變的。則方法內(nèi)修改了這個(gè)可變對(duì)象,源對(duì)象也發(fā)生了變化。
?
83.參數(shù)的類型_位置參數(shù)_默認(rèn)值參數(shù)_命名參數(shù)
參數(shù)的幾種類型
位置參數(shù)
函數(shù)調(diào)用時(shí),實(shí)參默認(rèn)按位置順序傳遞,需要個(gè)數(shù)和形參匹配。按位置傳遞的參數(shù),稱為: ???“位置參數(shù)”。
def f1(a,b,c):
print(a,b,c)
f1(2,3,4)
默認(rèn)值參數(shù)
我們可以為某些參數(shù)設(shè)置默認(rèn)值,這樣這些參數(shù)在傳遞時(shí)就是可選的。稱為“默認(rèn)值參數(shù)”。 默認(rèn)值參數(shù)放到位置參數(shù)后面。
def?f1(a,b,c=10,d=20):? ? ? ? ? ? ? ? ?#默認(rèn)值參數(shù)必須位于普通位置參數(shù)后面print(a,b,c,d)
f1(8,9)
f1(8,9,19)
f1(8,9,19,29)
命名參數(shù)
我們也可以按照形參的名稱傳遞參數(shù),稱為“命名參數(shù)”,也稱“關(guān)鍵字參數(shù)”。
def f1(a,b,c):
print(a,b,c)
f1(c=10,a=20,b=30)? ? ? ? ?#命名參數(shù)
84.參數(shù)的類型_可變參數(shù)_強(qiáng)制命名參數(shù)
可變參數(shù)
可變參數(shù)指的是“可變數(shù)量的參數(shù)”。分兩種情況:
1.*param(一個(gè)星號(hào)),將多個(gè)參數(shù)收集到一個(gè)“元組”對(duì)象中。
2.**param(兩個(gè)星號(hào)),將多個(gè)參數(shù)收集到一個(gè)“字典”對(duì)象中。
>>>def f3(a,b,*c,**d):
>>>print(a,b,c,d)
>>>f3(8,9,20,30,name='gaoqi',age=18)
>>>8 9 (20, 30) {'name': 'gaoqi', 'age': 18}
強(qiáng)制命名參數(shù)
在帶星號(hào)的“可變參數(shù)”后面增加新的參數(shù),必須在調(diào)用的時(shí)候“強(qiáng)制命名參數(shù)”。
85.lambda表達(dá)式和匿名函數(shù)
lambda表達(dá)式和匿名函數(shù)
lambda 表達(dá)式可以用來(lái)聲明匿名函數(shù)。lambda 函數(shù)是一種簡(jiǎn)單的、在同一行中定義函數(shù)的方法。lambda 函數(shù)實(shí)際生成了一個(gè)函數(shù)對(duì)象。lambda?表達(dá)式只允許包含一個(gè)表達(dá)式,不能包含復(fù)雜語(yǔ)句,該表達(dá)式的計(jì)算結(jié)果就是函數(shù)的返回值。
lambda 表達(dá)式的基本語(yǔ)法如下:
lambda arg1,arg2,arg3... : <表達(dá)式>
arg1/arg2/arg3 為函數(shù)的參數(shù)。<表達(dá)式>相當(dāng)于函數(shù)體。運(yùn)算結(jié)果是:表達(dá)式的運(yùn)算結(jié)果。
f = lambda a,b,c:a+b+c print(f(2,3,4))g = [lambda a:a*2,lambda b:b*3,lambda c:c*4] print(g[0](6),g[1](7),g[2](8))86.eval()函數(shù)用法
eval()函數(shù)
功能:將字符串 str 當(dāng)成有效的表達(dá)式來(lái)求值并返回計(jì)算結(jié)果。語(yǔ)法: eval(source[, globals[, locals]]) -> value
參數(shù):
source:一個(gè) Python 表達(dá)式或函數(shù) compile()返回的代碼對(duì)象
globals:可選。必須是 dictionary
locals:可選。任意映射對(duì)象
87.遞歸函數(shù)_函數(shù)調(diào)用內(nèi)存分析_棧幀的創(chuàng)建
遞歸函數(shù)
遞歸函數(shù)指的是:自己調(diào)用自己的函數(shù),在函數(shù)體內(nèi)部直接或間接的自己調(diào)用自己。遞歸類似于大家中學(xué)數(shù)學(xué)學(xué)習(xí)過(guò)的“數(shù)學(xué)歸納法”。 每個(gè)遞歸函數(shù)必須包含兩個(gè)部分:
1.終止條件
表示遞歸什么時(shí)候結(jié)束。一般用于返回值,不再調(diào)用自己。
2.遞歸步驟
把第 n 步的值和第 n-1 步相關(guān)聯(lián)。遞歸函數(shù)由于會(huì)創(chuàng)建大量的函數(shù)對(duì)象、過(guò)量的消耗內(nèi)存和運(yùn)算能力。在處理大量數(shù)據(jù)時(shí),謹(jǐn)慎使用。
最先調(diào)用,最后執(zhí)行?
88.遞歸函數(shù)_階乘計(jì)算案例
?使用遞歸函數(shù)計(jì)算階乘(factorial)
def factorial(n):if n==1:return 1 else:return n*factorial(n-1) 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Python基础知识(第六天)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python基础知识(第五天)
- 下一篇: Python基础知识(第七天)