python學習筆記——函數及記憶體分析

2020-08-08 14:10:17

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

返回值return

還可以結束函數的執行
在这里插入图片描述

def my_avg(a, b):
    return (a + b) / 2


c = my_avg(20, 30)
print(c)
25.0

在这里插入图片描述

def add(a, b):
    print("計算兩個參數{0},{1}的和:{2}".format(a, b, (a + b)))
    return a + b


def text02(x, y, z):
    return [x ** 2, y ** 2, z ** 2]


c = add(20, 30)
print(c)
d = text02(2, 3, 4)
print(d)
50
[4, 9, 16]

區域性變數全域性變數

區域性變數a與全域性變數a是完全兩個物件,函數裡優先只區域性變數
在这里插入图片描述

參數的傳遞_傳遞可變物件_記憶體分析

可變物件

a = [10, 20]
print(id(a))
print(a)
print("*****************************************")

def test01(m):
    print(id(m))
    m.append(300)
    print(id(m))  # 由於a是可變物件,所以m地址不變

test01(a)
print(a)
2144395747912
[10, 20]
*****************************************
2144395747912
2144395747912
[10, 20, 300]

注:

  1. a是一個棧,相對應數據值存在堆中;m是一個棧幀,相對應數據值也存在堆中
  2. 如果呼叫函數,會啓動一個棧幀m,結束後即消失
  3. m是區域性變數,呼叫時m與a的地址一模一樣
  4. 由於此處a是可變物件,所以可修改

參數的傳遞_傳遞不可變物件_記憶體分析

a = 100
def f1(n):
    print("n:", id(n))  # 傳遞進來的是a物件的地址
    n = n + 200  # 由於a是不可變物件,因此建立新的物件n(id不同)
    print("n:",id(n))  # n已經變成了新的物件
    print(n)
f1(a)
print("a:",id(a))
n: 140706869780384
n: 2288594194384  # 輸出地址變了,不再是原來的n了
300
a: 140706869780384

淺拷貝和深拷貝_記憶體分析

淺拷貝:只拷貝物件本身,不包含該物件參照的其他物件
深拷貝:連帶該物件參照的所有相關的物件(兒子孫子家庭)全拷貝

import copy

a = [10, 20, [5, 6]]
b = copy.copy(a)

print("a:",a)
print("b:",b)

b.append(30)
b[2].append(7)

print("淺拷貝……")
print("a:", a)
print("b:", b)
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6]]
淺拷貝……
a: [10, 20, [5, 6, 7]]  # b中包含的下一子物件依舊是a中的,
b: [10, 20, [5, 6, 7], 30]  # 改b中該物件即a中的

在这里插入图片描述

a = [10, 20, [5, 6]]
b = copy.deepcopy(a)

print("a:", a)
print("b:", b)

b.append(30)
b[2].append(7)

print("深拷貝……")
print("a:", a)
print("b:", b)
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6]]
深拷貝……
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6, 7], 30]

深拷貝則全部拷貝了過來,b怎麼改都不會影響到a了

參數的傳遞_不可變物件含可變子物件_記憶體分析


a = (10, 20, [5, 6])
print("a:", id(a))

def test01(m):
    print("m:", id(m))
    m[0] = 20  # 這樣會報錯,元組不可變
    print(m)
    print("m:", id(m))


test01(a)

傳遞不可變物件時,如果包含的子物件是可變的,則可修改


a = (10, 20, [5, 6])
print("a:", id(a))

def test01(m):
    print("m:", id(m))
    m[2][0] = 888  # 改變元組內層列表元素的值
    print(m)
    print("m:", id(m))


test01(a)
print(a)
a: 1925259481304
m: 1925259481304  # m的id不變,仍是那個物件
(10, 20, [888, 6])
m: 1925259481304
(10, 20, [888, 6])  # a也跟隨m的變化改變了

在这里插入图片描述
注:綠色圈圈包含的是不可修改的

參數的幾種型別

位置參數

預設值參數

def test01(a, b = 10, c = 20)# 預設值參數必須位於普通位置參數後面
    print(a,b,c)

test01(8,9,19)  # 可通過傳遞新值覆蓋預設值

命名參數

def f1(a, b, c):
    print(a, b, c)


f1(8, 9, 10)  # 位置參數
f1(c=10, a=20, b=30)  # 命名參數

可變參數

指可變數量的參數

def f1(a,b,*c)  # 將多個參數收集到一個元組c中
    print(a,b,c)

f1(8,9,19,20)  # 將19,20收集到c中
def f2(a,b,**c)  # # 將多個參數收集到一個字典c中
    print(a,b,c)

f1(8,9,name='celia',age=20)
def f2(a,b,*d,**c):  # 注意順序是先元組後字典
    print(a,b,c,d)

f1(8,9,30,40,name='celia',age=20)

強制命名參數

可變參數後如果還要加參數,需要強制命名

def f2(*d, a, b):
    print(a, b, d)


f2(8, 9, a=30, b=40)

lambda表達式和匿名函數

在这里插入图片描述

在這裏插入程式碼片

eval()函數用法

可從外部傳進來

遞回函數_函數呼叫記憶體分析_棧幀的建立

遞回函數:自己呼叫自己的函數,在函數內部直接或間接的自己呼叫自己
先執行的後呼叫