gpt4 book ai didi

python - 了解 Python 3.7 中类、namedtuple 和 __slots__ 的大小

转载 作者:太空宇宙 更新时间:2023-11-04 02:03:34 25 4
gpt4 key购买 nike

在观看了 Nina Zahkarenko 在 Pycon2016 ( link ) 上的 Python 内存管理演讲后,dunder 方法 __slots__ 似乎是一种减少对象大小和加速属性查找的工具。

我的期望是普通类是最大的,而 __slots__/namedtuple 方法会节省空间。但是,使用 sys.getsizeof() 进行的快速实验似乎表明情况并非如此:

from collections import namedtuple
from sys import getsizeof

class Rectangle:
'''A class based Rectangle, with a full __dict__'''
def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height

class SlotsRectangle:
'''A class based Rectangle with __slots__ defined for attributes'''
__slots__ = ('x', 'y', 'width', 'height')

def __init__(self, x, y, width, height):
self.x = x
self.y = y
self.width = width
self.height = height

NamedTupleRectangle = namedtuple('Rectangle', ('x', 'y', 'width', 'height'))
NamedTupleRectangle.__doc__ = 'A rectangle as an immutable namedtuple'

print(f'Class: {getsizeof(Rectangle(1,2,3,4))}')
print(f'Slots: {getsizeof(SlotsRectangle(1,2,3,4))}')
print(f'Named Tuple: {getsizeof(NamedTupleRectangle(1,2,3,4))}')

终端输出:

$ python3.7 example.py
Class: 56
Slots: 72
Named Tuple: 80

这是怎么回事?来自 Python 的文档 Data Model似乎描述符用于 __slots__ 这会增加实现它的类的函数开销。然而,为什么结果如此严重地偏向于普通类(class)?

引导我内心的 Raymond H.:必须有更难的方法!

最佳答案

sys.getsizeof() 函数可能没有按照您的预期进行;它不适用于复杂对象,例如自定义类。

this answer用于计算对象内存大小的方法;也许它可以帮助你。我从此处复制了该答案的代码,但完整的解释在我链接的答案中。

import sys
from numbers import Number
from collections import Set, Mapping, deque

try: # Python 2
zero_depth_bases = (basestring, Number, xrange, bytearray)
iteritems = 'iteritems'
except NameError: # Python 3
zero_depth_bases = (str, bytes, Number, range, bytearray)
iteritems = 'items'

def getsize(obj_0):
"""Recursively iterate to sum size of object & members."""
_seen_ids = set()
def inner(obj):
obj_id = id(obj)
if obj_id in _seen_ids:
return 0
_seen_ids.add(obj_id)
size = sys.getsizeof(obj)
if isinstance(obj, zero_depth_bases):
pass # bypass remaining control flow and return
elif isinstance(obj, (tuple, list, Set, deque)):
size += sum(inner(i) for i in obj)
elif isinstance(obj, Mapping) or hasattr(obj, iteritems):
size += sum(inner(k) + inner(v) for k, v in getattr(obj, iteritems)())
# Check for custom object instances - may subclass above too
if hasattr(obj, '__dict__'):
size += inner(vars(obj))
if hasattr(obj, '__slots__'): # can have __slots__ with __dict__
size += sum(inner(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s))
return size
return inner(obj_0)

关于python - 了解 Python 3.7 中类、namedtuple 和 __slots__ 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55221477/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com