国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

流暢的python讀書筆記-第八章-對象引用、可變性和垃圾回收

zgbgx / 1861人閱讀

摘要:運算符比較兩個對象的標識函數返回對象標識的整數表示。實際上,每個對象都會統計有多少引用指向自己。對象被銷毀了,調用了回調,的值變成了。當對象的引用數量歸零后,垃圾回收程序會把對象銷毀。引用的目標對象稱為所指對象。

對象不是個盒子

class Gizmo:
    def __init__(self):
        print("Gizmo id: %d" % id(self))

x = Gizmo()
print(x)

y = Gizmo() * 10
print(y)

print(dir())
? 輸出的 Gizmo id: ... 是創建 Gizmo 實例的副作用。
? 在乘法運算中使用 Gizmo 實例會拋出異常。
? 這里表明,在嘗試求積之前其實會創建一個新的 Gizmo 實例。
? 但是,肯定不會創建變量 y,因為在對賦值語句的右邊進行求值時拋出了異常。
 為了理解 Python 中的賦值語句,應該始終先讀右邊。對象在右邊創建或獲取,在此之后左邊的變量才會綁定到對象上,
標識、相等性和別名
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 運算符和 id 函數確認了這一點。
? 向 liang 中添加一個元素相當于向 longe 中添加一個元素。

在那段代碼中,liang 和 longe 是別名,即兩個變量綁定同一個對象。
而 other 不是 longe 的別名,因為二者綁定的是不同的對象。

other 和longe 綁定的對象具有相同的值(== 比較的就是值),但是它們的標識不同。

每個變量都有標識、類型和值。對象一旦創建,它的標識絕不會變;

你可以把標識理解為對象在內存中的地址。

is 運算符比較兩個對象的標識;

id() 函數返回對象標識的整數表示。

在==和is之間選擇

== 運算符比較兩個對象的值(對象中保存的數據),而 is 比較對象的標識。

is 運算符比 == 速度快,因為它不能重載,所以 Python 不用尋找并調用特殊方法,而是 直接比較兩個整數 ID

eq 方法,會考慮對象屬性的值。相等性測試可能涉及大量處理工作,例如,比較大型集合或嵌套層級深的結構時。

元組的相對不可變性

元組的不可變性其實是指 tuple 數據結構的物理內容(即保存的引用)不可變,與引用的對象無關

元組的值會隨著引用的可變對象的變化而變。

元組中不可變的是元素的標識。內存地址

>>> 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
基礎理解!!!還是可以的
默認淺復制
>>> l1 = [3, [55, 44], (7, 8, 9)]
>>> l2 = list(l1) ?
>>> l2
[3, [55, 44], (7, 8, 9)]
>>> l2 == l1 ?
True
>>> l2 is l1 ?
False

然而,構造方法或 [:] 做的是淺復制(即復制了最外層容器,副本中的元素是源容器中
元素的引用)。如果所有元素都是不可變的,那么這樣沒有問題,還能節省內存。

為任意對象做深復制和淺復制
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 屬性后發現,bus1 和 bus2 共享同一個列表對象,因為 bus2 是
bus1 的淺復制副本。
? bus3 是 bus1 的深復制副本,因此它的 passengers 屬性指代另一個列表。

注意,一般來說,深復制不是件簡單的事。如果對象有循環引用,那么這個樸素的算法會進入無限循環
深復制
>>> a = [10, 20]
>>> b = [a, 30]
>>> a.append(b)
>>> a
[10, 20, [[...], 30]]
>>> from copy import deepcopy
>>> c = deepcopy(a)
>>> c
[10, 20, [[...], 30]]
深復制有時可能太深了。例如,對象可能會引用不該復制的外部資源或單例值。我們可以實現特殊方法 __copy__() 和 __deepcopy__(),控制 copy 和 deepcopy 的行為
函數的參數作為引用時

共享傳參指函數的各個形式參數獲得實參中各個引用的副本。也就是說,函數內部的形參
是實參的別名。

def f(a, b):
    a += b
    return a


a = [1, 2]
b = [3, 4]

print(f(a, b))
print(a, b)

這里變量全都是引用,無論局部變量還是全局.
所以上面案例中,a會變化

不要使用可變類型作為參數的默認值
class HauntedBus:
    """備受幽靈乘客折磨的校車"""
    def __init__(self, passengers=[]):  #別使用這種可變類型 作為默認參數
        self.passengers = passengers 
防御性編程(對待可變類型)
class TwilightBus:
    """正常的校車"""

    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 = TwilightBus(("sfs", "sdf"))
bus2 = TwilightBus(["sdfsdfsfd111"])

bus1.pick("ppxia")
bus1.drop("sfs")
print(bus1.passengers)

bus2.drop("sdfsdfsfd111")
print(bus2.passengers)
http://www.pythontutor.com/vi...
盡量別用可變類型做默認參數值, 實在要用,必須使其產生副本
del和垃圾回收

有個 del 特殊方法,但是它不會銷毀實例,不應該在代碼中調用。

即將銷毀實例時,Python 解釋器會調用 del 方法,給實例最后的機會,釋放外資源。

自己編寫的代碼很少需要實現 del 代碼,有些 Python 新手會花時間實現,但卻吃力不討好,因為 del 很難用對。

垃圾計數器

在 CPython 中,垃圾回收使用的主要算法是引用計數。

實際上,每個對象都會統計有多少引用指向自己。

當引用計數歸零時,對象立即就被銷毀:CPython 會在對象上調用__del__ 方法(如果定義了),然后釋放分配給對象的內存。

為了演示對象生命結束時的情形,示例 8-16 使用 weakref.finalize 注冊一個回調函數,在銷毀對象時調用。
>>> 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 不刪除對象,而是刪除對象的引用。
? 重新綁定最后一個引用 s2,讓 {1, 2, 3} 無法獲取。對象被銷毀了,調用了 bye 回
調,ender.alive 的值變成了 False。

 弱引用

正是因為有引用,對象才會在內存中存在。當對象的引用數量歸零后,垃圾回收程序會把對象銷毀。但是,有時需要引用對象,而不讓對象存在的時間超過所需時間。

弱引用不會增加對象的引用數量。引用的目標對象稱為所指對象(referent)。因此我們說,弱引用不會妨礙所指對象被當作垃圾回收。

弱引用在緩存應用中很有用,因為我們不想僅因為被緩存引用著而始終保存緩存對象。

弱引用是可調用的對象,返回的是被引用的對象;
>>> 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

? 調用 wref() 返回的是被引用的對象,{0, 1}。因為這是控制臺會話,所以 {0, 1}
會綁定給 _ 變量。
? a_set 不再指代 {0, 1} 集合,因此集合的引用數量減少了。但是 _ 變量仍然指代
它。
? 調用 wref() 依舊返回 {0, 1}。
? 計算這個表達式時,{0, 1} 存在,因此 wref() 不是 None。但是,隨后 _ 綁定到結
果值 False?,F在 {0, 1} 沒有強引用了。
? 因為 {0, 1} 對象不存在了,所以 wref() 返回 None。

弱引用到此為止,用到再來查 page 289 總結

變量的不是盒子,是便利貼(就是c的指針)

==是值相等 is是(內存地址相等)

默認是淺復制,就內存地址復制.深復制會有一些過深危險(可以重寫特殊方法 __copy__() 和 __deepcopy__())

盡量別用可變類型做默認參數值, 實在要用,必須使其產生副本

實際上,每個對象都會統計有多少引用指向自己。 Cpython中, 當引用計數歸零時,對象立即就被銷毀:CPython會在對象上調用__del__ 方法(如果定義了),然后釋放分配給對象的內存

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/41681.html

相關文章

  • 讀書筆記之深入理解Java虛擬機

    摘要:前言本文內容基本摘抄自深入理解虛擬機,以供復習之用,沒有多少參考價值。此區域是唯一一個在虛擬機規范中沒有規定任何情況的區域。堆是所有線程共享的內存區域,在虛擬機啟動時創建。虛擬機上把方法區稱為永久代。 前言 本文內容基本摘抄自《深入理解Java虛擬機》,以供復習之用,沒有多少參考價值。想要更詳細了解請參考原書。 第二章 1.運行時數據區域 showImg(https://segment...

    jaysun 評論0 收藏0
  • 《java 8 實戰》讀書筆記 -八章 重構、測試調試

    摘要:通常,這種模式是通過定義一個代表處理對象的抽象類來實現的,在抽象類中會定義一個字段來記錄后續對象。工廠模式使用表達式第章中,我們已經知道可以像引用方法一樣引用構造函數。 一、為改善可讀性和靈活性重構代碼 1.改善代碼的可讀性 Java 8的新特性也可以幫助提升代碼的可讀性: 使用Java 8,你可以減少冗長的代碼,讓代碼更易于理解 通過方法引用和Stream API,你的代碼會變得更...

    gclove 評論0 收藏0
  • [譯] 與 Python 無縫集成——基本特殊方法 4

    摘要:當引用計數為零,則不再需要該對象且可以銷毀。這表明當變量被刪除時引用計數正確的變為零。方法只能在循環被打破后且引用計數已經為零時調用。這兩步的過程允許引用計數或垃圾收集刪除已引用的對象,讓弱引用懸空。這允許在方法設置對象屬性值之前進行處理。 注:原書作者 Steven F. Lott,原書名為 Mastering Object-oriented Python __del__()方法 ...

    Allen 評論0 收藏0
  • Python學習之路27-對象引用、變性垃圾回收

    摘要:函數的參數作為引用時唯一支持的參數傳遞模式是共享傳參,它指函數的形參獲得實參中各個引用的副本,即形參是實參的別名。而在上面這個例子中,類的屬性實際上是形參所指向的對象所指對象,的別名。 《流暢的Python》筆記本篇是面向對象慣用方法的第一篇,一共六篇。本篇主要是一些概念性的討論,內容有:Python中的變量,對象標識,值,別名,元組的某些特性,深淺復制,引用,函數參數,垃圾回收,de...

    Batkid 評論0 收藏0

發表評論

0條評論

zgbgx

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<