自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python 變量?對(duì)象?引用?賦值?一個(gè)例子解釋清楚

開發(fā) 前端
在 Python 中,變量實(shí)際上是對(duì)象的【引用】,而不是對(duì)象本身的【存儲(chǔ)】。當(dāng)我們執(zhí)行賦值語(yǔ)句時(shí),會(huì)自動(dòng)建立變量和對(duì)象之間的關(guān)系,即引用。

哈嘍大家好,我是咸魚。

前天有個(gè)小伙伴找到我,給了我一段 python 代碼:

a = [1, 2]
a[1] = a
print(a[1])

然后問(wèn)我為什么結(jié)果是 [1, [...]],我一看這個(gè)問(wèn)題有意思,我說(shuō)三言兩語(yǔ)解釋不清楚,寫篇文章到時(shí)候你看下吧,于是有了今天這篇文章。

在正式開始之前,讓我們先弄清楚一些概念。

對(duì)象?變量?引用?賦值?

"Python 中一切皆對(duì)象",相信這句話大家在學(xué)習(xí) Python 的時(shí)候都已經(jīng)聽的耳朵起繭子了吧。

在 Python 中,所有的數(shù)據(jù)都是對(duì)象,包括基本數(shù)據(jù)類型(例如整數(shù)、浮點(diǎn)數(shù)、字符串等)以及用戶自定義的類型(類的實(shí)例等)。

而對(duì)象其實(shí)是內(nèi)存中分配的一塊空間,用來(lái)存儲(chǔ)其值。每個(gè)對(duì)象都有一個(gè)唯一的標(biāo)識(shí)符(id),可以通過(guò) id() 函數(shù)獲取。

不但如此,每一個(gè)對(duì)象都具有兩個(gè)標(biāo)準(zhǔn)的頭部信息:

  • 類型標(biāo)志符(Type Identifier):每個(gè)對(duì)象都有一個(gè)類型信息,可以通過(guò) type() 函數(shù)獲取。
  • 引用計(jì)數(shù)器(Reference Counter): 引用計(jì)數(shù)器表示有多少個(gè)引用指向該對(duì)象,當(dāng)引用計(jì)數(shù)降為零時(shí),對(duì)象會(huì)被垃圾回收。( Python 也使用其他垃圾回收機(jī)制,例如循環(huán)垃圾回收器來(lái)處理引用環(huán)的情況。)

在 Python 中,變量實(shí)際上是對(duì)象的【引用】,而不是對(duì)象本身的【存儲(chǔ)】。當(dāng)我們執(zhí)行賦值語(yǔ)句時(shí),會(huì)自動(dòng)建立變量和對(duì)象之間的關(guān)系,即引用。

變量就像是一個(gè)指針,【指向】?jī)?nèi)存中存儲(chǔ)對(duì)象的位置。

我們來(lái)看一個(gè)例子:

a = 1
b = a
a = a + 1

首先將  1 賦值于  a,即 a 指向了  1  這個(gè)對(duì)象。

接著 b = a 則表示讓變量 b 也同時(shí)指向 1 這個(gè)對(duì)象。Python 的對(duì)象可以被多個(gè)變量所指向(引用)。

最后執(zhí)行 a = a + 1,在這里需要注意的是,Python 的基礎(chǔ)數(shù)據(jù)類型(例如整型(int)、字符串(string)等)是不可變的

所以,a = a + 1,并不是讓 a 的值增加 1,而是表示重新創(chuàng)建了一個(gè)新的值為 2 的對(duì)象,并讓 a 指向它。但是 b 仍然不變,仍然指向 1 這個(gè)對(duì)象。

因此最后的結(jié)果是,a 的值變成了 2,而 b的值不變?nèi)匀皇?nbsp;1。

通過(guò)這個(gè)例子你可以看到,這里的 a 和 b,開始只是兩個(gè)指向同一個(gè)對(duì)象的變量而已,或者你也可以把它們想象成同一個(gè)對(duì)象的兩個(gè)名字。

簡(jiǎn)單的賦值 b = a,并不表示重新創(chuàng)建了新對(duì)象,只是讓同一個(gè)對(duì)象被多個(gè)變量指向或引用。

為什么?

在了解了變量、對(duì)象、引用、賦值之后,我們回到一開始的例子。

a = [1, 2]
a[1] = a
print(a[1])

這段代碼中創(chuàng)建了一個(gè)列表 a,其中包含兩個(gè)元素(1 和 2),然后 a[1] 被賦值為整個(gè)列表 a(a[1] = a),當(dāng)你打印 a[1] 時(shí),它實(shí)際上是指向列表 a 本身。

a = [1, <reference to a>]

這樣就會(huì)導(dǎo)致循環(huán)引用的問(wèn)題。

我們來(lái)分步驟解釋一下這個(gè)過(guò)程:

  • a 是一個(gè)包含兩個(gè)元素的列表:[1, 2]。
  • a[1] = a 將列表 a 的第二個(gè)元素設(shè)為 a,即a[1]實(shí)際上指向列表 a 本身,形成了一個(gè)循環(huán)引用
  • 當(dāng)打印 a[1] 時(shí),Python 發(fā)現(xiàn)這是一個(gè)特殊的情況,即這個(gè)元素是對(duì)列表本身的引用。為了避免無(wú)限循環(huán),Python 會(huì)顯示 ...,表示引用已經(jīng)進(jìn)入了一個(gè)循環(huán)。因此看到的結(jié)果是 [1, [...]]。

那如何避免循環(huán)引用呢?可以使用淺拷貝或者深拷貝來(lái)解決。

我們用淺拷貝來(lái)試一下:

import copy

a = [1, 2]
a[1] = copy.copy(a)
print(a[1])

# 結(jié)果是[1,2]

淺拷貝創(chuàng)建一個(gè)新的對(duì)象,然后將原始對(duì)象中的元素復(fù)制到新對(duì)象中。但是,如果原始對(duì)象的元素是可變對(duì)象(例如列表),那么淺拷貝只會(huì)復(fù)制對(duì)象的引用而不是對(duì)象本身。

就比如上面的例子:

  • a = [1, 2] 創(chuàng)建了一個(gè)列表 a,其中有兩個(gè)元素 1 和 2。
  • a[1] = copy.copy(a) 將列表 a 的第二個(gè)元素修改為對(duì)列表 a 的淺拷貝。
  • 打印 a[1],此時(shí) a[1] 指向了新的對(duì)象 [1, 2]
責(zé)任編輯:趙寧寧 來(lái)源: 咸魚運(yùn)維雜談
相關(guān)推薦

2023-03-14 08:02:14

靜態(tài)路由動(dòng)態(tài)路由設(shè)備

2009-06-11 14:48:48

jbpm工作流引擎jbpm例子

2009-06-18 15:53:37

Hibernate B

2024-01-08 13:40:00

并發(fā)安全? 數(shù)量

2023-11-06 13:55:59

聯(lián)合索引MySQ

2022-01-05 08:58:08

Python解釋器編程語(yǔ)言

2018-01-02 09:44:37

2022-10-08 13:29:19

Pandasgroupby

2021-07-09 06:11:37

Java泛型Object類型

2021-04-21 11:08:00

數(shù)據(jù)分析數(shù)據(jù)集Python

2019-12-27 16:21:54

Python 開發(fā)編程語(yǔ)言

2024-08-14 13:24:24

2023-04-20 13:59:01

Pythonwhile循環(huán)的

2018-04-02 10:37:10

Linux命令size

2024-01-31 08:16:38

IPythonPython解釋器

2024-06-12 12:03:15

Python變量代碼

2023-01-05 18:14:32

淺拷貝深拷貝Python

2025-03-03 08:40:00

JavaScriptthis開發(fā)

2020-12-25 11:11:48

鴻蒙HarmonyOS應(yīng)用開發(fā)

2022-08-01 10:44:37

人工智能AI
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)