日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

提高代碼效率的六個Python內存優化技巧

來源: 責編: 時間:2024-01-16 17:31:31 229觀看
導讀當項目變得越來越大時,有效地管理計算資源是一個不可避免的需求。Python與C或c++等低級語言相比,似乎不夠節省內存。但是其實有許多方法可以顯著優化Python程序的內存使用,這些方法可能在實際應用中并沒有人注意,所以本文

當項目變得越來越大時,有效地管理計算資源是一個不可避免的需求。Python與C或c++等低級語言相比,似乎不夠節省內存。6Tc28資訊網——每日最新資訊28at.com

但是其實有許多方法可以顯著優化Python程序的內存使用,這些方法可能在實際應用中并沒有人注意,所以本文將重點介紹Python的內置機制,掌握它們將大大提高Python編程技能。6Tc28資訊網——每日最新資訊28at.com

6Tc28資訊網——每日最新資訊28at.com

首先在進行內存優化之前,我們首先要查看內存的使用情況6Tc28資訊網——每日最新資訊28at.com

分配了多少內存?

有幾種方法可以在Python中獲取對象的大小。可以使用sys.getsizeof()來獲取對象的確切大小,使用objgraph.show_refs()來可視化對象的結構,或者使用psutil.Process().memory_info()。RSS獲取當前分配的所有內存。6Tc28資訊網——每日最新資訊28at.com

>>> import numpy as np >>> import sys >>> import objgraph >>> import psutil >>> import pandas as pd   >>> ob = np.ones((1024, 1024, 1024, 3), dtype=np.uint8)  ### Check object 'ob' size >>> sys.getsizeof(ob) / (1024 * 1024) 3072.0001373291016  ### Check current memory usage of whole process (include ob and installed packages, ...) >>> psutil.Process().memory_info().rss / (1024 * 1024) 3234.19140625  ### Check structure of 'ob' (Useful for class object) >>> objgraph.show_refs([ob], filename='sample-graph.png')  ### Check memory for pandas.DataFrame >>> from sklearn.datasets import load_boston >>> data = load_boston() >>> data = pd.DataFrame(data['data']) >>> print(data.info(verbose=False, memory_usage='deep')) <class 'pandas.core.frame.DataFrame'> RangeIndex: 506 entries, 0 to 505 Columns: 13 entries, 0 to 12 dtypes: float64(13) memory usage: 51.5 KB    ### Check memory for pandas.Series >>> data[0].memory_usage(deep=True)   # deep=True to include all the memory used by underlying parts that construct the pd.Series 4176

這樣我們才能根據對象的內存占用來查看實際的優化結果6Tc28資訊網——每日最新資訊28at.com

__slots__

Python作為一種動態類型語言,在面向對象方面具有更大的靈活性。在運行時可以向Python類添加額外屬性和方法的能力。6Tc28資訊網——每日最新資訊28at.com

例如,下面的代碼定義了一個名為Author的類。最初它有兩個屬性name和age。但是我們以后可以很容易地添加一個額外的job:6Tc28資訊網——每日最新資訊28at.com

class Author:    def __init__(self, name, age):        self.name = name        self.age = age   me = Author('Yang Zhou', 30) me.job = 'Software Engineer' print(me.job) # Software Engineer

但是這種靈活性在底層浪費了更多內存。6Tc28資訊網——每日最新資訊28at.com

因為Python中每個類的實例都維護一個特殊的字典(__dict__)來存儲實例變量。因為字典的底層基于哈希表的實現所以消耗了大量的內存。6Tc28資訊網——每日最新資訊28at.com

在大多數情況下,我們不需要在運行時更改實例的變量或方法,并且__dict__不會(也不應該)在類定義后更改。所以Python為此提供了一個屬性:__slots__。6Tc28資訊網——每日最新資訊28at.com

它通過指定類的所有有效屬性的名稱來作為白名單:6Tc28資訊網——每日最新資訊28at.com

class Author:    __slots__ = ('name', 'age')     def __init__(self, name, age):        self.name = name        self.age = age   me = Author('Yang Zhou', 30) me.job = 'Software Engineer' print(me.job) # AttributeError: 'Author' object has no attribute 'job'

白名單只定義了兩個有效的屬性name和age。由于屬性是固定的,Python不需要為它維護字典,只為__slots__中定義的屬性分配必要的內存空間。6Tc28資訊網——每日最新資訊28at.com

下面我們做一個簡單的比較:6Tc28資訊網——每日最新資訊28at.com

import sys   class Author:    def __init__(self, name, age):        self.name = name        self.age = age   class AuthorWithSlots:    __slots__ = ['name', 'age']     def __init__(self, name, age):        self.name = name        self.age = age   # Creating instances me = Author('Yang', 30) me_with_slots = AuthorWithSlots('Yang', 30)  # Comparing memory usage memory_without_slots = sys.getsizeof(me) + sys.getsizeof(me.__dict__) memory_with_slots = sys.getsizeof(me_with_slots) # __slots__ classes don't have __dict__  print(memory_without_slots, memory_with_slots) # 152 48 print(me.__dict__) # {'name': 'Yang', 'age': 30} print(me_with_slots.__dict__) # AttributeError: 'AuthorWithSlots' object has no attribute '__dict__'

可以看到 152 和 48 明顯節省了內存。6Tc28資訊網——每日最新資訊28at.com

Generators

生成器是Python中列表的惰性求值版本。每當調用next()方法時生成一個項,而不是一次計算所有項。所以它們在處理大型數據集時非常節省內存。6Tc28資訊網——每日最新資訊28at.com

def number_generator():    for i in range(100):        yield i  numbers = number_generator() print(numbers) # <generator object number_generator at 0x104a57e40> print(next(numbers)) # 0 print(next(numbers)) # 1

上面的代碼顯示了一個編寫和使用生成器的基本示例。關鍵字yield是生成器定義的核心。應用它意味著只有在調用next()方法時才會產生項i。6Tc28資訊網——每日最新資訊28at.com

讓我們比較一個生成器和一個列表,看看哪個更節省內存:6Tc28資訊網——每日最新資訊28at.com

mport sys  numbers = [] for i in range(100):    numbers.append(i)  def number_generator():    for i in range(100):        yield i  numbers_generator = number_generator() print(sys.getsizeof(numbers_generator)) # 112 print(sys.getsizeof(numbers)) # 920

可以看到使用生成器可以顯著節省內存使用。如果我們將列表推導式的方括號轉換成圓括號,它將成為生成器表達式。這是在Python中定義生成器的更簡單的方法:6Tc28資訊網——每日最新資訊28at.com

import sys  numbers = [i for i in range(100)] numbers_generator = (i for i in range(100))  print(sys.getsizeof(numbers_generator)) # 112 print(sys.getsizeof(numbers)) # 920

利用內存映射文件支持大文件處理

內存映射文件I/O,簡稱“mmap”,是一種操作系統級優化。6Tc28資訊網——每日最新資訊28at.com

簡單地說,當使用mmap技術對文件進行內存映射時,它直接在當前進程的虛擬內存空間中創建文件的映射,而不是將整個文件加載到內存中,這節省了大量內存。6Tc28資訊網——每日最新資訊28at.com

Python已經提供了用于使用此技術的內置模塊,因此我們可以輕松地利用它,而無需考慮操作系統級別的實現。6Tc28資訊網——每日最新資訊28at.com

以下是如何在Python中使用mmap進行文件處理:6Tc28資訊網——每日最新資訊28at.com

import mmap   with open('test.txt', "r+b") as f:    # memory-map the file, size 0 means whole file    with mmap.mmap(f.fileno(), 0) as mm:        # read content via standard file methods        print(mm.read())        # read content via slice notation        snippet = mm[0:10]        print(snippet.decode('utf-8'))

Python使內存映射文件I/O技術的使用變得方便。我們所需要做的只是應用mmap.mmap()方法,然后使用標準文件方法甚至切片符號處理打開的對象。6Tc28資訊網——每日最新資訊28at.com

選擇適當的數據類型

開發人員應仔細而精確地選擇數據類型。因為在某些情況下,使用一種數據類型比使用另一種數據類型更節省內存。6Tc28資訊網——每日最新資訊28at.com

1、元組比列表更節省內存

元組是不可變的(在創建后不能更改),它允許Python在內存分配方面進行優化。列表是可變的,因此需要額外的空間來容納潛在的修改。6Tc28資訊網——每日最新資訊28at.com

import sys  my_tuple = (1, 2, 3, 4, 5) my_list = [1, 2, 3, 4, 5]  print(sys.getsizeof(my_tuple)) # 80 print(sys.getsizeof(my_list))  # 120

元組my_tuple比列表使用更少的內存,如果創建后不需要更改數據,我們應該選擇元組而不是列表。6Tc28資訊網——每日最新資訊28at.com

2、數組比列表更節省內存

Python中的數組要求元素具有相同的數據類型(例如,所有整數或所有浮點數),但列表可以存儲不同類型的對象,這不可避免地需要更多的內存。如果列表的元素都是相同類型,使用數組會更節省內存:6Tc28資訊網——每日最新資訊28at.com

import sys import array  my_list = [i for i in range(1000)]  my_array = array.array('i', [i for i in range(1000)])  print(sys.getsizeof(my_list))   # 8856 print(sys.getsizeof(my_array))  # 4064

另外:Python是數據科學的主導語言。有許多強大的第三方模塊和工具提供更多的數據類型,如NumPy和Pandas。如果我們只需要一個簡單的一維數字數組,而不需要NumPy提供的廣泛功能,那么Python的內置數組是一個不錯的選擇。但當涉及到復雜的矩陣操作時,使用NumPy提供的數組是所有數據科學家的首選,也可能是最佳選擇。6Tc28資訊網——每日最新資訊28at.com

字符串駐留

看看下面的代碼:6Tc28資訊網——每日最新資訊28at.com

>>> a = 'Y'*4096 >>> b = 'Y'*4096 >>> a is b True >>> c = 'Y'*4097 >>> d = 'Y'*4097 >>> c is d False

為什么a是b是真,而c是d是假呢?6Tc28資訊網——每日最新資訊28at.com

這在Python中被稱作字符串駐留(string interning).如果有幾個值相同的小字符串,它們將被Python隱式地存儲并在內存中并引用相同的對象。定義小字符串閾值數字是4096。6Tc28資訊網——每日最新資訊28at.com

由于c和d的長度為4097,因此它們是內存中的兩個對象而不是一個對象,不再隱式駐留字符串。所以當執行c = d時,我們得到一個False。6Tc28資訊網——每日最新資訊28at.com

駐留是一種優化內存使用的強大技術。如果我們想要顯式地使用它可以使用sys.intern()方法:6Tc28資訊網——每日最新資訊28at.com

>>> import sys >>> c = sys.intern('Y'*4097) >>> d = sys.intern('Y'*4097) >>> c is d True

本文鏈接:http://www.www897cc.com/showinfo-26-62787-0.html提高代碼效率的六個Python內存優化技巧

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 深入剖析PyPy,解鎖Python比C還快的秘訣

下一篇: 花 15 分鐘把 Express.js 搞明白,全棧沒有那么難

標簽:
  • 熱門焦點
  • 影音體驗是真的強 簡單聊聊iQOO Pad

    大公司的好處就是產品線豐富,非常細分化的東西也能給你做出來,例如早先我們看到了新的vivo Pad2,之后我們又在iQOO Neo8 Pro的發布會上看到了iQOO的首款平板產品iQOO Pad。雖
  • 2023年Q2用戶偏好榜:12+256G版本成新主流

    3月份的性能榜、性價比榜和好評榜之后,就要輪到2023年的第二季度偏好榜了,上半年的新機潮已經過去,最明顯的肯定就是大內存和存儲的機型了,另外部分中端機也取消了屏幕塑料支架
  • 跑分安卓第一!Redmi K60至尊版8月發布!盧偉冰:目標年度性能之王

    8月5日消息,Redmi K60至尊版將于8月發布,在此前舉行的戰略發布會上,官方該機將搭載搭載天璣9200+處理器,安兔兔V10跑分超177萬分,是目前安卓陣營最高的分數
  • Automa-通過連接塊來自動化你的瀏覽器

    1、前言通過瀏覽器插件可實現自動化腳本的錄制與編寫,具有代表性的工具就是:Selenium IDE、Katalon Recorder,對于簡單的業務來說可快速實現自動化的上手工作。Selenium IDEKat
  • 在線圖片編輯器,支持PSD解析、AI摳圖等

    自從我上次分享一個人開發仿造稿定設計的圖片編輯器到現在,不知不覺已過去一年時間了,期間我經歷了裁員失業、面試找工作碰壁,寒冬下一直沒有很好地履行計劃.....這些就放在日
  • 一個注解實現接口冪等,這樣才優雅!

    場景碼猿慢病云管理系統中其實高并發的場景不是很多,沒有必要每個接口都去考慮并發高的場景,比如添加住院患者的這個接口,具體的業務代碼就不貼了,業務偽代碼如下:圖片上述代碼有
  • 慕巖炮轟抖音,百合網今何在?

    來源:價值研究所 作者:Hernanderz&ldquo;難道就因為自己的一個產品牛逼了,從客服到總裁,都不愿意正視自己產品和運營上的問題,選擇逃避了嗎?&rdquo;這一番話,出自百合網聯合創
  • 支持aptX Lossless無損傳輸 iQOO TWS 1賽道版發布限時優惠價369元

    2023年7月4日,“無損音質,聲動人心”iQOO TWS 1正式發布,支持aptX Lossless無損傳輸,限時優惠價369元。iQOO TWS 1耳機率先支持端到端aptX Lossless無
  • 利用職權私自解除被封帳號 Meta開除20多名員工

    11月18日消息,據外媒援引知情人士表示,過去一年時間內,Facebook母公司Meta解雇或處罰了20多名員工以及合同工,指控這些人通過內部系統以不當方式重置用戶帳號,其
Top 主站蜘蛛池模板: 岳西县| 洛南县| 万宁市| 南汇区| 盐山县| 察雅县| 临清市| 衡阳县| 麻阳| 多伦县| 琼海市| 阿克陶县| 本溪市| 清原| 濮阳县| 贡山| 兴化市| 舟曲县| 周宁县| 绥江县| 比如县| 樟树市| 阳高县| 鹤岗市| 阿鲁科尔沁旗| 佳木斯市| 青海省| 蒙山县| 班玛县| 巴马| 鄂尔多斯市| 灯塔市| 福鼎市| 奉节县| 芮城县| 东山县| 自治县| 广汉市| 烟台市| 垦利县| 金湖县|