成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發 前端
當項目變得越來越大時,有效地管理計算資源是一個不可避免的需求。Python與C或c++等低級語言相比,似乎不夠節省內存。

當項目變得越來越大時,有效地管理計算資源是一個不可避免的需求。Python與C或c++等低級語言相比,似乎不夠節省內存。

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

首先在進行內存優化之前,我們首先要查看內存的使用情況。

分配了多少內存?

有幾種方法可以在Python中獲取對象的大小。可以使用sys.getsizeof()來獲取對象的確切大小,使用objgraph.show_refs()來可視化對象的結構,或者使用psutil.Process().memory_info()。RSS獲取當前分配的所有內存。

>>> 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

這樣我們才能根據對象的內存占用來查看實際的優化結果。

__slots__

Python作為一種動態類型語言,在面向對象方面具有更大的靈活性。在運行時可以向Python類添加額外屬性和方法的能力。

例如,下面的代碼定義了一個名為Author的類。最初它有兩個屬性name和age。但是我們以后可以很容易地添加一個額外的job:

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

但是這種靈活性在底層浪費了更多內存。

因為Python中每個類的實例都維護一個特殊的字典(__dict__)來存儲實例變量。因為字典的底層基于哈希表的實現所以消耗了大量的內存。

在大多數情況下,我們不需要在運行時更改實例的變量或方法,并且__dict__不會(也不應該)在類定義后更改。所以Python為此提供了一個屬性:__slots__。

它通過指定類的所有有效屬性的名稱來作為白名單:

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__中定義的屬性分配必要的內存空間。

下面我們做一個簡單的比較:

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 明顯節省了內存。

Generators

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

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。

讓我們比較一個生成器和一個列表,看看哪個更節省內存:

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中定義生成器的更簡單的方法:

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”,是一種操作系統級優化。

簡單地說,當使用mmap技術對文件進行內存映射時,它直接在當前進程的虛擬內存空間中創建文件的映射,而不是將整個文件加載到內存中,這節省了大量內存。

Python已經提供了用于使用此技術的內置模塊,因此我們可以輕松地利用它,而無需考慮操作系統級別的實現。

以下是如何在Python中使用mmap進行文件處理:

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()方法,然后使用標準文件方法甚至切片符號處理打開的對象。

選擇適當的數據類型

開發人員應仔細而精確地選擇數據類型。因為在某些情況下,使用一種數據類型比使用另一種數據類型更節省內存。

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

元組是不可變的(在創建后不能更改),它允許Python在內存分配方面進行優化。列表是可變的,因此需要額外的空間來容納潛在的修改。

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比列表使用更少的內存,如果創建后不需要更改數據,我們應該選擇元組而不是列表。

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

Python中的數組要求元素具有相同的數據類型(例如,所有整數或所有浮點數),但列表可以存儲不同類型的對象,這不可避免地需要更多的內存。如果列表的元素都是相同類型,使用數組會更節省內存:

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提供的數組是所有數據科學家的首選,也可能是最佳選擇。

字符串駐留

看看下面的代碼:

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

為什么a是b是真,而c是d是假呢?

這在Python中被稱作字符串駐留(string interning).如果有幾個值相同的小字符串,它們將被Python隱式地存儲并在內存中并引用相同的對象。定義小字符串閾值數字是4096。

由于c和d的長度為4097,因此它們是內存中的兩個對象而不是一個對象,不再隱式駐留字符串。所以當執行c = d時,我們得到一個False。

駐留是一種優化內存使用的強大技術。如果我們想要顯式地使用它可以使用sys.intern()方法:

>>> import sys
 >>> c = sys.intern('Y'*4097)
 >>> d = sys.intern('Y'*4097)
 >>> c is d
 True
責任編輯:華軒 來源: DeepHub IMBA
相關推薦

2017-05-03 10:45:47

Python運行效率竅門

2019-01-07 07:57:27

物聯網運營效率IOT

2011-04-29 17:01:44

打印機優化原則

2022-08-17 10:14:17

數據中心能源消耗制冷

2014-08-20 13:59:13

Linux

2022-04-29 17:03:37

WordPress開發者網站安全

2024-03-06 10:50:30

云計算云實例云提供商

2016-12-15 09:53:07

自學編程技巧

2020-03-29 11:46:16

前端開發前端工具

2021-10-09 10:00:52

遠程招聘技巧招聘

2015-08-04 10:51:26

vim效率技巧

2024-07-15 08:10:57

2023-02-08 17:00:07

IF 語句技巧代碼

2015-07-30 14:43:04

導航欄iOS開發

2023-10-10 18:24:46

PostgreSQL性能RDBMS

2022-09-05 14:17:48

Javascript技巧

2023-01-29 07:45:06

DevOps

2022-06-28 10:17:23

安全職位首席信息安全官

2021-02-05 16:20:54

代碼Linux技巧

2023-05-22 15:53:06

JavaScrip代碼素材
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91原创视频在线观看 | 国产成人综合亚洲欧美94在线 | 二区av| 亚洲一区视频在线 | 在线观看国产视频 | 免费看一级毛片 | 日韩欧美中文在线 | 91久久精| 综合久久综合久久 | 亚洲三级国产 | www亚洲免费国内精品 | 色在线看 | 69精品久久久久久 | 日韩第一区 | 亚洲精品久久 | 国产精品久久久久久久久久 | 免费成年网站 | 天堂综合网久久 | 天天操夜夜操免费视频 | 99精品久久久久久中文字幕 | 亚洲一区二区三区免费观看 | 中文字幕一区二区三区乱码在线 | 色综合中文 | 日韩精品亚洲专区在线观看 | 亚洲国产中文字幕 | 国产精品欧美日韩 | 国产高清在线精品 | 99在线观看视频 | 亚洲一区在线播放 | 99精品观看| 国产精品久久久久久妇女 | 国产精品免费观看 | 黄色网页在线 | 一区二区三区视频在线观看 | 激情久久av一区av二区av三区 | 欧美成年人网站 | 91精品综合久久久久久五月天 | 国产成人综合一区二区三区 | 成人午夜视频在线观看 | 久久天天躁狠狠躁夜夜躁2014 | 亚洲一区二区三区在线视频 |