摘要:運(yùn)算符比較兩個(gè)對(duì)象的標(biāo)識(shí)函數(shù)返回對(duì)象標(biāo)識(shí)的整數(shù)表示。實(shí)際上,每個(gè)對(duì)象都會(huì)統(tǒng)計(jì)有多少引用指向自己。對(duì)象被銷(xiāo)毀了,調(diào)用了回調(diào),的值變成了。當(dāng)對(duì)象的引用數(shù)量歸零后,垃圾回收程序會(huì)把對(duì)象銷(xiāo)毀。引用的目標(biāo)對(duì)象稱為所指對(duì)象。
對(duì)象不是個(gè)盒子
class Gizmo: def __init__(self): print("Gizmo id: %d" % id(self)) x = Gizmo() print(x) y = Gizmo() * 10 print(y) print(dir())
? 輸出的 Gizmo id: ... 是創(chuàng)建 Gizmo 實(shí)例的副作用。
? 在乘法運(yùn)算中使用 Gizmo 實(shí)例會(huì)拋出異常。
? 這里表明,在嘗試求積之前其實(shí)會(huì)創(chuàng)建一個(gè)新的 Gizmo 實(shí)例。
? 但是,肯定不會(huì)創(chuàng)建變量 y,因?yàn)樵趯?duì)賦值語(yǔ)句的右邊進(jìn)行求值時(shí)拋出了異常。
longe = {"name": "longe", "born": 1993} liang = longe print(liang is longe) print(id(liang), id(longe)) longe["balance"] = 950 print(liang) ## 冒充的longe信息 other = {"name": "longe", "born": 1993, "balance": 950} print(other) print(other is longe)
? liang 是 longe 的別名。
? is 運(yùn)算符和 id 函數(shù)確認(rèn)了這一點(diǎn)。
? 向 liang 中添加一個(gè)元素相當(dāng)于向 longe 中添加一個(gè)元素。
在那段代碼中,liang 和 longe 是別名,即兩個(gè)變量綁定同一個(gè)對(duì)象。
而 other 不是 longe 的別名,因?yàn)槎呓壎ǖ氖遣煌膶?duì)象。other 和longe 綁定的對(duì)象具有相同的值(== 比較的就是值),但是它們的標(biāo)識(shí)不同。
每個(gè)變量都有標(biāo)識(shí)、類(lèi)型和值。對(duì)象一旦創(chuàng)建,它的標(biāo)識(shí)絕不會(huì)變;
你可以把標(biāo)識(shí)理解為對(duì)象在內(nèi)存中的地址。
is 運(yùn)算符比較兩個(gè)對(duì)象的標(biāo)識(shí);
id() 函數(shù)返回對(duì)象標(biāo)識(shí)的整數(shù)表示。
在==和is之間選擇== 運(yùn)算符比較兩個(gè)對(duì)象的值(對(duì)象中保存的數(shù)據(jù)),而 is 比較對(duì)象的標(biāo)識(shí)。
is 運(yùn)算符比 == 速度快,因?yàn)樗荒苤剌d,所以 Python 不用尋找并調(diào)用特殊方法,而是 直接比較兩個(gè)整數(shù) ID
eq 方法,會(huì)考慮對(duì)象屬性的值。相等性測(cè)試可能涉及大量處理工作,例如,比較大型集合或嵌套層級(jí)深的結(jié)構(gòu)時(shí)。
元組的相對(duì)不可變性元組的不可變性其實(shí)是指 tuple 數(shù)據(jù)結(jié)構(gòu)的物理內(nèi)容(即保存的引用)不可變,與引用的對(duì)象無(wú)關(guān)
元組的值會(huì)隨著引用的可變對(duì)象的變化而變。
元組中不可變的是元素的標(biāo)識(shí)。內(nèi)存地址
>>> t1 = (1, 2, [30, 40]) ? >>> t2 = (1, 2, [30, 40]) ? >>> t1 == t2 ? True >>> id(t1[-1]) ? 4302515784 >>> t1[-1].append(99) ? >>> t1 (1, 2, [30, 40, 99]) >>> id(t1[-1]) ? 4302515784 >>> t1 == t2 ? False
基礎(chǔ)理解!!!還是可以的默認(rèn)淺復(fù)制
>>> l1 = [3, [55, 44], (7, 8, 9)] >>> l2 = list(l1) ? >>> l2 [3, [55, 44], (7, 8, 9)] >>> l2 == l1 ? True >>> l2 is l1 ? False
然而,構(gòu)造方法或 [:] 做的是淺復(fù)制(即復(fù)制了最外層容器,副本中的元素是源容器中
元素的引用)。如果所有元素都是不可變的,那么這樣沒(méi)有問(wèn)題,還能節(jié)省內(nèi)存。
import copy class Bus: def __init__(self, passengers=None): if passengers is None: self.passengers = [] else: self.passengers = list(passengers) def pick(self, name): self.passengers.append(name) def drop(self, name): self.passengers.remove(name) bus1 = Bus(["Alice", "Bill", "Claire", "David"]) bus2 = copy.copy(bus1) bus3 = copy.deepcopy(bus1) print(id(bus1), id(bus2), id(bus3)) bus1.drop("Bill") print(bus2.passengers) print(id(bus1.passengers), id(bus2.passengers), id(bus3.passengers)) print(bus3.passengers)
? 審查 passengers 屬性后發(fā)現(xiàn),bus1 和 bus2 共享同一個(gè)列表對(duì)象,因?yàn)?bus2 是
bus1 的淺復(fù)制副本。
? bus3 是 bus1 的深復(fù)制副本,因此它的 passengers 屬性指代另一個(gè)列表。
注意,一般來(lái)說(shuō),深復(fù)制不是件簡(jiǎn)單的事。如果對(duì)象有循環(huán)引用,那么這個(gè)樸素的算法會(huì)進(jìn)入無(wú)限循環(huán)深復(fù)制
>>> a = [10, 20] >>> b = [a, 30] >>> a.append(b) >>> a [10, 20, [[...], 30]] >>> from copy import deepcopy >>> c = deepcopy(a) >>> c [10, 20, [[...], 30]]
深復(fù)制有時(shí)可能太深了。例如,對(duì)象可能會(huì)引用不該復(fù)制的外部資源或單例值。我們可以實(shí)現(xiàn)特殊方法 __copy__() 和 __deepcopy__(),控制 copy 和 deepcopy 的行為函數(shù)的參數(shù)作為引用時(shí)
共享傳參指函數(shù)的各個(gè)形式參數(shù)獲得實(shí)參中各個(gè)引用的副本。也就是說(shuō),函數(shù)內(nèi)部的形參
是實(shí)參的別名。
def f(a, b): a += b return a a = [1, 2] b = [3, 4] print(f(a, b)) print(a, b)
這里變量全都是引用,無(wú)論局部變量還是全局.
所以上面案例中,a會(huì)變化
class HauntedBus: """備受幽靈乘客折磨的校車(chē)""" def __init__(self, passengers=[]): #別使用這種可變類(lèi)型 作為默認(rèn)參數(shù) self.passengers = passengers防御性編程(對(duì)待可變類(lèi)型)
class TwilightBus: """正常的校車(chē)""" def __init__(self, passengers=None): if passengers is None: self.passengers = [] else: self.passengers = list(passengers) ##這里會(huì)產(chǎn)生副本(可以理解為深拷貝) def pick(self, name): self.passengers.append(name) def drop(self, name): self.passengers.remove(name) bus1 = TwilightBus(("sfs", "sdf")) bus2 = TwilightBus(["sdfsdfsfd111"]) bus1.pick("ppxia") bus1.drop("sfs") print(bus1.passengers) bus2.drop("sdfsdfsfd111") print(bus2.passengers)
盡量別用可變類(lèi)型做默認(rèn)參數(shù)值, 實(shí)在要用,必須使其產(chǎn)生副本del和垃圾回收
有個(gè) del 特殊方法,但是它不會(huì)銷(xiāo)毀實(shí)例,不應(yīng)該在代碼中調(diào)用。
即將銷(xiāo)毀實(shí)例時(shí),Python 解釋器會(huì)調(diào)用 del 方法,給實(shí)例最后的機(jī)會(huì),釋放外資源。
自己編寫(xiě)的代碼很少需要實(shí)現(xiàn) del 代碼,有些 Python 新手會(huì)花時(shí)間實(shí)現(xiàn),但卻吃力不討好,因?yàn)?del 很難用對(duì)。
垃圾計(jì)數(shù)器在 CPython 中,垃圾回收使用的主要算法是引用計(jì)數(shù)。
實(shí)際上,每個(gè)對(duì)象都會(huì)統(tǒng)計(jì)有多少引用指向自己。
當(dāng)引用計(jì)數(shù)歸零時(shí),對(duì)象立即就被銷(xiāo)毀:CPython 會(huì)在對(duì)象上調(diào)用__del__ 方法(如果定義了),然后釋放分配給對(duì)象的內(nèi)存。
為了演示對(duì)象生命結(jié)束時(shí)的情形,示例 8-16 使用 weakref.finalize 注冊(cè)一個(gè)回調(diào)函數(shù),在銷(xiāo)毀對(duì)象時(shí)調(diào)用。>>> import weakref >>> s1 = {1, 2, 3} >>> s2 = s1 ? >>> def bye(): ? ... print("Gone with the wind...") ... >>> ender = weakref.finalize(s1, bye) ? >>> ender.alive ? True >>> del s1 >>> ender.alive ? True >>> s2 = "spam" ? Gone with the wind... >>> ender.alive False
? 如前所述,del 不刪除對(duì)象,而是刪除對(duì)象的引用。
? 重新綁定最后一個(gè)引用 s2,讓 {1, 2, 3} 無(wú)法獲取。對(duì)象被銷(xiāo)毀了,調(diào)用了 bye 回
調(diào),ender.alive 的值變成了 False。
正是因?yàn)橛幸茫瑢?duì)象才會(huì)在內(nèi)存中存在。當(dāng)對(duì)象的引用數(shù)量歸零后,垃圾回收程序會(huì)把對(duì)象銷(xiāo)毀。但是,有時(shí)需要引用對(duì)象,而不讓對(duì)象存在的時(shí)間超過(guò)所需時(shí)間。
弱引用不會(huì)增加對(duì)象的引用數(shù)量。引用的目標(biāo)對(duì)象稱為所指對(duì)象(referent)。因此我們說(shuō),弱引用不會(huì)妨礙所指對(duì)象被當(dāng)作垃圾回收。
弱引用在緩存應(yīng)用中很有用,因?yàn)槲覀儾幌雰H因?yàn)楸痪彺嬉弥冀K保存緩存對(duì)象。
弱引用是可調(diào)用的對(duì)象,返回的是被引用的對(duì)象;>>> import weakref >>> a_set = {0, 1} >>> wref = weakref.ref(a_set) ? >>> wref>>> wref() ? {0, 1} >>> a_set = {2, 3, 4} ? >>> wref() ? {0, 1} >>> wref() is None ? False >>> wref() is None ? True
? 調(diào)用 wref() 返回的是被引用的對(duì)象,{0, 1}。因?yàn)檫@是控制臺(tái)會(huì)話,所以 {0, 1}
會(huì)綁定給 _ 變量。
? a_set 不再指代 {0, 1} 集合,因此集合的引用數(shù)量減少了。但是 _ 變量仍然指代
它。
? 調(diào)用 wref() 依舊返回 {0, 1}。
? 計(jì)算這個(gè)表達(dá)式時(shí),{0, 1} 存在,因此 wref() 不是 None。但是,隨后 _ 綁定到結(jié)
果值 False。現(xiàn)在 {0, 1} 沒(méi)有強(qiáng)引用了。
? 因?yàn)?{0, 1} 對(duì)象不存在了,所以 wref() 返回 None。
變量的不是盒子,是便利貼(就是c的指針)
==是值相等 is是(內(nèi)存地址相等)
默認(rèn)是淺復(fù)制,就內(nèi)存地址復(fù)制.深復(fù)制會(huì)有一些過(guò)深危險(xiǎn)(可以重寫(xiě)特殊方法 __copy__() 和 __deepcopy__())
盡量別用可變類(lèi)型做默認(rèn)參數(shù)值, 實(shí)在要用,必須使其產(chǎn)生副本
實(shí)際上,每個(gè)對(duì)象都會(huì)統(tǒng)計(jì)有多少引用指向自己。 Cpython中, 當(dāng)引用計(jì)數(shù)歸零時(shí),對(duì)象立即就被銷(xiāo)毀:CPython會(huì)在對(duì)象上調(diào)用__del__ 方法(如果定義了),然后釋放分配給對(duì)象的內(nèi)存
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/41681.html
摘要:前言本文內(nèi)容基本摘抄自深入理解虛擬機(jī),以供復(fù)習(xí)之用,沒(méi)有多少參考價(jià)值。此區(qū)域是唯一一個(gè)在虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何情況的區(qū)域。堆是所有線程共享的內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。虛擬機(jī)上把方法區(qū)稱為永久代。 前言 本文內(nèi)容基本摘抄自《深入理解Java虛擬機(jī)》,以供復(fù)習(xí)之用,沒(méi)有多少參考價(jià)值。想要更詳細(xì)了解請(qǐng)參考原書(shū)。 第二章 1.運(yùn)行時(shí)數(shù)據(jù)區(qū)域 showImg(https://segment...
摘要:通常,這種模式是通過(guò)定義一個(gè)代表處理對(duì)象的抽象類(lèi)來(lái)實(shí)現(xiàn)的,在抽象類(lèi)中會(huì)定義一個(gè)字段來(lái)記錄后續(xù)對(duì)象。工廠模式使用表達(dá)式第章中,我們已經(jīng)知道可以像引用方法一樣引用構(gòu)造函數(shù)。 一、為改善可讀性和靈活性重構(gòu)代碼 1.改善代碼的可讀性 Java 8的新特性也可以幫助提升代碼的可讀性: 使用Java 8,你可以減少冗長(zhǎng)的代碼,讓代碼更易于理解 通過(guò)方法引用和Stream API,你的代碼會(huì)變得更...
摘要:當(dāng)引用計(jì)數(shù)為零,則不再需要該對(duì)象且可以銷(xiāo)毀。這表明當(dāng)變量被刪除時(shí)引用計(jì)數(shù)正確的變?yōu)榱恪7椒ㄖ荒茉谘h(huán)被打破后且引用計(jì)數(shù)已經(jīng)為零時(shí)調(diào)用。這兩步的過(guò)程允許引用計(jì)數(shù)或垃圾收集刪除已引用的對(duì)象,讓弱引用懸空。這允許在方法設(shè)置對(duì)象屬性值之前進(jìn)行處理。 注:原書(shū)作者 Steven F. Lott,原書(shū)名為 Mastering Object-oriented Python __del__()方法 ...
摘要:函數(shù)的參數(shù)作為引用時(shí)唯一支持的參數(shù)傳遞模式是共享傳參,它指函數(shù)的形參獲得實(shí)參中各個(gè)引用的副本,即形參是實(shí)參的別名。而在上面這個(gè)例子中,類(lèi)的屬性實(shí)際上是形參所指向的對(duì)象所指對(duì)象,的別名。 《流暢的Python》筆記本篇是面向?qū)ο髴T用方法的第一篇,一共六篇。本篇主要是一些概念性的討論,內(nèi)容有:Python中的變量,對(duì)象標(biāo)識(shí),值,別名,元組的某些特性,深淺復(fù)制,引用,函數(shù)參數(shù),垃圾回收,de...
閱讀 998·2023-04-26 02:21
閱讀 2818·2021-09-24 09:47
閱讀 1608·2019-08-30 15:55
閱讀 2164·2019-08-30 14:01
閱讀 2320·2019-08-29 14:01
閱讀 2048·2019-08-29 12:46
閱讀 815·2019-08-26 13:27
閱讀 1933·2019-08-26 12:23