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