日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python申请内存函数_python进阶用法2 【从帮助函数看python内存申请机制】

發布時間:2024/10/8 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python申请内存函数_python进阶用法2 【从帮助函数看python内存申请机制】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

介紹了四個幫助函數,dir(),help(),type(),id(),通過id()函數進一步分析了python在申請內存方面的效率問題,提到的基本類型有string,list,queue和deque

四個幫助函數

dir()函數

dir()函數是查看函數或模塊內的操作方法都有什么,輸出的是方法列表。

dir('str')

也可以查看自己定義的函數

help()函數

help()函數是查看函數或模塊用途的詳細說明,例:

help('str')

type()函數

這個很簡單了,返回其類型,略

id()函數

對一個對象的引用調用id()函數,可以得到該對象的標識符(dentity).該標識符是一個整數,它保證在該對象的生命周期內是唯一的和恒定的.具有不重疊生命周期的兩個對象具有相同的id()值.

PS: 在CPython實現細節:標識符(dentity)為對象在內存中的地址. 在Python中一切皆對象,變量中存放的是對象的引用.字符串常量和整型常量都是對象.

舉個例子:

>>> a = 1

>>> b=2

>>> c =1

>>> id(a)

1521120064

>>> id(b)

1521120096

>>> id(c)

1521120064

不知道,在看這個dentity的時候,有沒有發現a與c的地址是相同的!!!

從id()函數看python內存地址申請機制

看個例子:(以下內容來源@Unname_Bao 關于python3中整數數組轉bytes的效率問題)

如果還是沒有理解的話,接下來看我本地進行的一個非常簡單的一個演示腳本測試:

import time

t1 = time.time()

astr = 'a'

for x in range(1,2000000):

astr = astr + str(x)

astr

t2 = time.time()

print(t2-t1)

#10.028913259506226

#[Finished in 10.2s]

import time

t1 = time.time()

astr = list('1'*2000000)

for x in range(1,2000000):

astr[x]=str(x)

bstr = str(astr)

t2 = time.time()

print(t2-t1)

#0.8323781490325928

#[Finished in 1.1s]

為什么差距如此之大呢?這就回到了我們最初提到的a,b,當值改變,會重新去申請內存空間(id改變)。在這第一個例子中,我們不停地改變astr的值,astr即不停地申請內存空間,此過程消耗了大量的時間!!!第二個例子中,我們一次申請了夠所有變量使用的內存空間地址,免去了每次申請,所以大大加快了運行速度!!!

感謝@一個閑散之人的閑散更進一步的分析,

影響其效率問題的核心根本在于list到底是基于鏈表的數據結構還是基于線性表的數據結構。線性表的話為了騰出足夠連續空間需要改變表頭的內存位置,也就造成了id的改變,對于鏈表而言,則只需要申請一個結點大小的內存量,沒必要對表頭的內存位置動手腳。

關于list的數據結構,從知乎上get到的結果是線性表形式的數據結構,于是乎我又做了以下3個測試:

1、不提前申請空間的queue

import time

import queue

t1 = time.time()

astr = queue.Queue()

for x in range(1,2000000):

astr.put(str(x))

bstr = str(astr)

t2 = time.time()

print(t2-t1)

# 4.525705337524414

# [Finished in 4.8s]

2、不提前申請空間的deque

import collections

import time

t1 = time.time()

astr = collections.deque()

for x in range(1,2000000):

astr.append(str(x))

bstr = str(astr)

t2 = time.time()

print(t2-t1)

# 0.938164234161377

# [Finished in 1.3s]

3、不提前申請空間的list

import time

t1 = time.time()

astr = []

for x in range(1,2000000):

astr.append(str(x))

bstr = str(astr)

t2 = time.time()

print(t2-t1)

# 0.9456796646118164

# [Finished in 1.2s]

另做個測試:

import collections

import queue

print("Deque ID:")

astr1 = collections.deque()

for x in range(1,5):

astr1.append(str(x))

print(id(astr1))

print("Queue ID:")

astr2 = queue.Queue()

for x in range(1,5):

astr2.put(str(x))

print(id(astr2))

print("list ID:")

astr3 = []

for x in range(1,5):

astr3.append(str(x))

print(id(astr3))

# Deque ID:

# 1206229307464

# 1206229307464

# 1206229307464

# 1206229307464

# Queue ID:

# 1206225595416

# 1206225595416

# 1206225595416

# 1206225595416

# list ID:

# 1206229266760

# 1206229266760

# 1206229266760

# 1206229266760

# [Finished in 0.2s]

queue、deque其實可以很明顯看出,其均是依靠c的鏈表進行開發的(不需要提前申請空間),其地址亦不變化。更改一點之前的錯誤理解,python的list實現不是鏈表,而是動態數組

當我們使用deque時,可以很明顯看到,我們的時間消耗已經差距很小了,與未提前申請空間的list接近一致,但經多次運行,還是可以發現,最快的依舊是已經申請了空間的list,我么進一步去了解queue和deque可以發現其無法提前申請空間(可以理解為其職能分別從一端和兩段進行增加值,減值),及無法像list一樣可以通過list[下標]直接取值,所以綜上所述,list無疑是最快的~

補充,list的擴張空間機制

>>> test = []

>>> test.__sizeof__()

40

>>> test.append('a')

>>> test.__sizeof__()

72

>>> test.append('a')

>>> test.__sizeof__()

72

>>> test.append('a')

>>> test.__sizeof__()

72

>>> test.append('a')

>>> test.__sizeof__()

72

>>> test.append('a')

>>> test.__sizeof__()

104

>>>

參考鏈接:Python中list的內存分配

總結

以上是生活随笔為你收集整理的python申请内存函数_python进阶用法2 【从帮助函数看python内存申请机制】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。