第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

Python 進(jìn)階應(yīng)用教程

Python 進(jìn)階應(yīng)用教程
01 Python 的對(duì)象和類 02 Python 類屬性和實(shí)例屬性 03 Python類的構(gòu)造方法、析構(gòu)方法、實(shí)例方法 04 Python 類的私有屬性和私有方法 05 Python 類的繼承和多繼承 06 Python 類實(shí)戰(zhàn) 07 Python 中的迭代器實(shí)現(xiàn)原理 08 Python 中的迭代器趣味實(shí)踐 09 Python 中的生成器實(shí)現(xiàn)原理 10 Python 中的生成器趣味實(shí)踐 11 Python 中的錯(cuò)誤和異常 12 Python 中的異常處理 13 Python 中的模塊 14 Python 標(biāo)準(zhǔn)庫之 os 模塊 15 Python 標(biāo)準(zhǔn)庫之 sys 模塊 16 Python 標(biāo)準(zhǔn)庫之 math 模塊 17 Python 標(biāo)準(zhǔn)庫之 random 模塊 18 Python 標(biāo)準(zhǔn)庫之 Json 模塊 19 Python 標(biāo)準(zhǔn)庫 datetime 模塊 20 Python 中的常用第三方模塊 21 Python 中的命名空間 22 Python 中的作用域 23 Python 中的文件 IO 操作 24 Python 基礎(chǔ)實(shí)戰(zhàn) 25 Python 內(nèi)置函數(shù) 26 Python 中使用正則表達(dá)式 27 使用 Python 操作 MySQL 數(shù)據(jù)庫 28 使用 Python 操作 Mongo 數(shù)據(jù)庫 29 使用 Python 操作 Redis 數(shù)據(jù)庫 30 使用 Python 發(fā)送一封郵件 31 threading 之 Thread 的使用 32 threading 之 Lock 的基本使用 33 Python 生產(chǎn)者消費(fèi)者模型 34 Python 的內(nèi)存管理與垃圾回收 35 Python 領(lǐng)域運(yùn)用:網(wǎng)絡(luò)爬蟲 36 Python 領(lǐng)域運(yùn)用:Web 開發(fā) 37 Python 領(lǐng)域運(yùn)用:自動(dòng)化運(yùn)維 38 Python 領(lǐng)域運(yùn)用:自動(dòng)化測(cè)試

Python 的內(nèi)存管理與垃圾回收

1. 內(nèi)存管理概述

1.1 手動(dòng)內(nèi)存管理

在計(jì)算機(jī)發(fā)展的早期,編程語言提供了手動(dòng)內(nèi)存管理的機(jī)制,例如 C 語言,提供了用于分配和釋放的函數(shù) malloc 和 free,如下所示:

#include <stdlib.h>

void *malloc(size_t size);
void free(void *p);
  • 函數(shù) malloc 分配指定大小 size 的內(nèi)存,返回內(nèi)存的首地址
  • 函數(shù) free 釋放之前申請(qǐng)的內(nèi)存

程序員負(fù)責(zé)保證內(nèi)存管理的正確性:使用 malloc 申請(qǐng)一塊內(nèi)存后,如果不再使用,需要使用 free 將其釋放,示例如下:

#include <stdlib.h>

void test()
{
    void *p = malloc(10);

    訪問 p 指向的內(nèi)存區(qū)域;

    free(p);
}

int main()
{
    test();
}
  • 使用 malloc(10) 分配一塊大小為 10 個(gè)字節(jié)的內(nèi)存區(qū)域
  • 使用 free§ 釋放這塊內(nèi)存區(qū)域

如果忘記釋放之前使用 malloc 申請(qǐng)的內(nèi)存,則會(huì)導(dǎo)致可用內(nèi)存不斷減少,這種現(xiàn)象被稱為 “內(nèi)存泄漏”,示例如下:

#include <stdio.h>
#include <stdlib.h>

void test()
{
    void *p = malloc(10);

    訪問 p 指向的內(nèi)存區(qū)域;
}

int main()
{
    while (1)
        test();
}
  • 在函數(shù) test 中,使用 malloc 申請(qǐng)一塊內(nèi)存
    • 但是使用完畢后,忘記釋放了這塊內(nèi)存
  • 在函數(shù) main 中,循環(huán)調(diào)用函數(shù) test()
    • 每次調(diào)用函數(shù) test(),都會(huì)造成內(nèi)存泄漏
    • 最終,會(huì)耗盡所有的內(nèi)存

1.2 自動(dòng)內(nèi)存管理

在計(jì)算機(jī)發(fā)展的早期,硬件性能很差,為了最大程度的壓榨硬件性能,編程語言提供了手動(dòng)管理內(nèi)存的機(jī)制。手動(dòng)管理內(nèi)存的機(jī)制的優(yōu)點(diǎn)在于能夠有效規(guī)劃和利用內(nèi)存,其缺點(diǎn)在于太繁瑣了,很容易出錯(cuò)。

隨著計(jì)算機(jī)的發(fā)展,硬件性能不斷提高,這時(shí)候出現(xiàn)的編程語言,例如:Java、C#、PHP、Python,則提供了自動(dòng)管理內(nèi)存的機(jī)制:程序員申請(qǐng)內(nèi)存后,不需要再顯式的釋放內(nèi)存,由編程語言的解釋器負(fù)責(zé)釋放內(nèi)存,從根本上杜絕了 “內(nèi)存泄漏” 這類錯(cuò)誤

在下面的 Python 程序中,在無限循環(huán)中不斷的申請(qǐng)內(nèi)存:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

while True:
    person = Person('tom', 13)
  • 類 Person 包含兩個(gè)屬性:name 和 age
  • 在 while 循環(huán)中,使用類 Person 生成一個(gè)實(shí)例 person
    • 需要申請(qǐng)一塊內(nèi)存用于保存實(shí)例 person 的屬性

Python 解釋器運(yùn)行這個(gè)程序時(shí),發(fā)現(xiàn)實(shí)例 person 不再被引用后,會(huì)自動(dòng)的釋放 person 占用的空間。因此這個(gè)程序可以永遠(yuǎn)的運(yùn)行下去,而不會(huì)把內(nèi)存耗盡。

2. 基于引用計(jì)數(shù)的內(nèi)存管理

2.1 基本原理

引用計(jì)數(shù)是一種最簡(jiǎn)單的自動(dòng)內(nèi)存管理機(jī)制:

  • 每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)
  • 當(dāng)把該對(duì)象賦值給一個(gè)變量時(shí),對(duì)象的引用計(jì)數(shù)遞增 1

引用計(jì)數(shù)的實(shí)例如下:

A = object()
B = A
A = None
B = None
  • 在第 1 行,使用 object() 創(chuàng)建一個(gè)對(duì)象,變量 A 指向該對(duì)象
    • 對(duì)象的引用計(jì)數(shù)變化為 1
  • 在第 2 行,變量 B 指向相同的對(duì)象
    • 對(duì)象的引用計(jì)數(shù)變化為 2
  • 在第 3 行,變量 A 指向 None
    • 對(duì)象的引用計(jì)數(shù)變化為 1
  • 在第 3 行,變量 B 指向 None
    • 對(duì)象的引用計(jì)數(shù)變化為 0

引用計(jì)數(shù)

從圖中可以看出,當(dāng)變量 A 和變量 B 都不再指向?qū)ο髸r(shí),對(duì)象的引用計(jì)數(shù)變?yōu)?0,系統(tǒng)檢測(cè)到該對(duì)象成為廢棄對(duì)象,可以將此廢棄對(duì)象回收。

2.2 優(yōu)點(diǎn)和缺點(diǎn)

引用計(jì)數(shù)的優(yōu)點(diǎn)在于:

  • 實(shí)現(xiàn)簡(jiǎn)單
  • 系統(tǒng)檢測(cè)到對(duì)象的引用計(jì)數(shù)變?yōu)?0 后,可以及時(shí)的釋放廢棄的對(duì)象
  • 處理回收內(nèi)存的時(shí)間分?jǐn)偟搅似綍r(shí)

引用計(jì)數(shù)的缺點(diǎn)在于:

  • 維護(hù)引用計(jì)數(shù)消耗性能,每次變量賦值時(shí),都需要維護(hù)維護(hù)引用計(jì)數(shù)
  • 無法釋放存在循環(huán)引用的對(duì)象

下面是一個(gè)存在循環(huán)引用的例子:

class Node:
    def __init__(self, data, next):
        self.data = data
        self.next = next

node = Node(123, None)
node.next = node
node = None
  • 在第 6 行,創(chuàng)建對(duì)象 node
    • 對(duì)象 node 的 next 指向 None
    • 此時(shí)對(duì)象 node 的引用計(jì)數(shù)為 1
  • 在第 7 行,對(duì)象 node 的 next 指向 node 自身
    • 此時(shí)對(duì)象 node 的引用計(jì)數(shù)為 2
  • 在第 7 行,對(duì)象 node 指向 None
    • 此時(shí)對(duì)象 node 的引用計(jì)數(shù)為 1

對(duì)象 node 的 next 字段指向自身,導(dǎo)致:即使沒有外部的變量指向?qū)ο?node,對(duì)象 node 的引用計(jì)數(shù)也不會(huì)變?yōu)?0,因此對(duì)象 node 就永遠(yuǎn)不會(huì)被釋放了。

3. 基于垃圾回收的內(nèi)存管理

3.1 基本原理

垃圾回收是目前主流的內(nèi)存管理機(jī)制:

  • 通過一系列的稱為 “GC Root” 的對(duì)象作為起始對(duì)象
  • 從 GC Root 出發(fā),進(jìn)行遍歷
  • 最終將對(duì)象劃分為兩類:
    • 從 GC Root 可以到達(dá)的對(duì)象
    • 從 GC Root 無法到達(dá)的對(duì)象

從 GC Root 無法到達(dá)的對(duì)象被認(rèn)為是廢棄對(duì)象,可以被系統(tǒng)回收。

垃圾回收

  • 在 Python 語言中,可作為 GC Roots 的對(duì)象主要是指全局變量指向的對(duì)象。
  • 從 GC Roots 出發(fā),可以到達(dá) object 1、object 2、object 3、object 4
  • 從 GC Roots 出發(fā),無法到達(dá) object 5、object 6、object 7,它們被判定為可回收的對(duì)象

3.2 優(yōu)點(diǎn)和缺點(diǎn)

垃圾回收的優(yōu)點(diǎn)在于:

  • 可以處理存在循環(huán)引用的對(duì)象

垃圾回收的缺點(diǎn)在于:

  • 實(shí)現(xiàn)復(fù)雜
  • 進(jìn)行垃圾回收時(shí),需要掃描程序中所有的對(duì)象,因此需要暫停程序的運(yùn)行。當(dāng)程序中對(duì)象數(shù)量較多時(shí),暫停程序的運(yùn)行時(shí)間過長(zhǎng),系統(tǒng)會(huì)有明顯的卡頓現(xiàn)象。

4. Python 的內(nèi)存管理機(jī)制

Python 的內(nèi)存管理采用了混合的方法:

  • Python 使用引用計(jì)數(shù)來保持追蹤內(nèi)存中的對(duì)象,當(dāng)對(duì)象的引用計(jì)數(shù)為 0 時(shí),回收該對(duì)象
  • Python 同時(shí)使用垃圾回收機(jī)制來回收存在有循環(huán)引用的對(duì)象

下面的例子中,演示了 Python 的內(nèi)存管理策略:

class Circular:
    def __init__(self):
        self.data = 0
        self.next = self

class NonCircular:
    def __init__(self):
        self.data = 0
        self.next = None

def hybrid():
    while True:
        circular = Circular()
        nonCircular = NonCircular()

hybrid()
  • 類 Circular,創(chuàng)建了一個(gè)包含循環(huán)引用的對(duì)象
    • self.next 指向自身,導(dǎo)致了循環(huán)引用
    • 類 Circular 的實(shí)例只能被垃圾回收機(jī)制釋放
  • 類 NonCircular,創(chuàng)建了一個(gè)不包含循環(huán)引用的對(duì)象
    • self.next 指向 None,沒有循環(huán)引用
    • 類 NonCircular 的實(shí)例可以引用計(jì)數(shù)機(jī)制釋放
  • 在方法 hybrid 中
    • 在無限循環(huán)中,不斷的申請(qǐng) Circular 實(shí)例和 NonCircular 實(shí)例

通過引用計(jì)數(shù)和垃圾回收機(jī)制,內(nèi)存不會(huì)被耗盡,程序可以永遠(yuǎn)的運(yùn)行下去。