日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

python 參數內存地址相關

作者:vincent_duan 更新時間: 2022-09-22 編程語言

查看下某個值的在內存中的地址

v1 = 'vincent'
print(id(v1))

v2 = [11,22,33]
v3 = [11,22,33]
print( id(v2) )
print( id(v3) )

我們需要知道的是當函數執行傳參時,傳遞的是內存地址。驗證:

def func(data):
    print(data, id(data)) # vincent 2398921260720

v1 = 'vincent'
func(v1)

print(id(v1)) # 2398921260720 

可以看出傳遞的是內存地址。

Python參數傳遞的特性好處是什么?

  • 主要是可以節省內存。如果執行函數時,每執行一次都要創建一個數據進行傳遞,那么有可能會將同一個數據創建很多遍,浪費內存空間。
  • 當傳遞內存地址的時候,可以讓函數幫我們對值的修改。例如:
def func(data):
    data.append(44)

v = [11,22,33]
func(v)
print(v)  # [11, 22, 33, 44]

因為vdata指向了同一塊內存,所以v的值發生了變化。

不過需要注意的是,要想實現對值的修改,參數必須是可變類型(list/dict/set),在函數內部只能對內部元素進行修改。

例如:

def func(data):
    data.upper() # str是不可變類型,無法進行修改

v = 'vincent'
func(v)
print(v) # vincent
def func(data):
    data = [44,55] # 不是對內部元素進行修改,而是重新賦值

v = [11,22,33]
func(v)
print(v) # [11, 22, 33]

深拷貝

如果想實現傳值而不是傳地址,那么可以使用深拷貝。

import copy

def func(data):
    data = [44,55]

v = [11,22,33]
new_v = copy.deepcopy(v) # 重新開辟一塊地址空間,不影響v的值
func(new_v)
print(v)

函數的返回值也是內存地址

def func():
    data = [11, 22, 33]
    print(id(data))  # 2875971195072
    return data

v1 = func()
print(v1, id(v1)) # [11,22,33] 2875971195072

上述代碼的執行過程:

  • 執行func函數
  • data = [11, 22, 33] 創建一塊內存區域,內部存儲[11,22,33],data變量指向這塊內存地址。
  • return data 返回data指向的內存地址
  • v1接收返回值,所以 v1 和 data 都指向 [11,22,33] 的內存地址(兩個變量指向此內存,引用計數器為2)
  • 由函數執行完畢之后,函數內部的變量都會被釋放。(即:刪除data變量,內存地址的引用計數器-1)

所以,最終v1指向的函數內部創建的那塊內存地址。

如果兩個函數進行調用,將返回不一樣的內存地址:

def func():
    data = [11, 22, 33]
    print(id(data))
    return data


v1 = func()
print(v1, id(v1))  # [11,22,33] 2187125510336

v2 = func()
print(v2, id(v2))  # [11,22,33] 2187126308352

需要注意的是,如果data是字符串或者整型時,會返回的地址是一樣的,涉及到Python的緩存機制,這里不表

參數的默認值

當我們在函數中定義了一個參數默認值之后,在函數定義之后,還未執行函數時,Python解釋器會幫助我們為函數創建一塊區域,存儲參數的默認值。

def func(a1,a2=18):
    print(a1,a2)

原理:Python在創建函數(未執行)時,如果發現函數的參數中有默認值,則在函數內部會創建一塊區域并維護這個默認值。

  • func("root"): 執行函數未傳值時,則讓a2指向 函數維護的那個值的地址。
  • func("admin",20):執行函數傳值時,則讓a2指向新傳入的值的地址。

在特定情況【默認參數的值是可變類型 list/dict/set】 & 【函數內部會修改這個值】下,參數的默認值 有坑 。

# 在函數定義的時候,a2初始化了,后面將不會重新初始化
def func(a1,a2=[1,2]):
    a2.append(666)
    print(a1,a2)

func(100) # 100 [1, 2, 666]
func(200) # 200 [1, 2, 666, 666] 
func(99, [77,88]) # 99 [77, 88, 666] a2重新指向了一個新的內存地址,但不影響剛初始化的那塊地址
func(300) # 300 [1, 2, 666, 666, 666] a2繼續用函數初始化的那塊地址

原文鏈接:https://blog.csdn.net/vincent_duan/article/details/125553573

欄目分類
最近更新