網站首頁 編程語言 正文
查看下某個值的在內存中的地址
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]
因為v
和data
指向了同一塊內存,所以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
- 上一篇:Python 閉包與裝飾器
- 下一篇:Python 短路運算符
相關推薦
- 2022-02-28 純 CSS實現根據元素已知的寬度設置高度以及注意事項
- 2022-10-30 Python接口傳輸url與flask數據詳解_python
- 2022-08-06 pythonfor循環中range與len區別_python
- 2024-03-28 Springboot maven加入本地jar,提示找不到類
- 2022-05-31 Android實現文件資源管理器雛形_Android
- 2022-05-12 小程序自定義日期組件,不顯示今日之后的日期
- 2022-03-29 python自動化之re模塊詳解_python
- 2022-11-14 解決“您的連接不是私密鏈接”的問題
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支