python - 内存中的数值存放机制(闲的)getsizeof、sizeof、__sizeof__嘛个意思,和id是一样的说!

本文探讨了Python中`getsizeof`和`id`函数的作用,指出`getsizeof`返回的并非列表及其内容的总内存占用,而是列表头部的占用空间。内容展示了列表元素如何通过指针链接,并分析了添加元素时列表大小的变化情况,揭示了Python内存管理的一角。
部署运行你感兴趣的模型镜像
In [88]: aa=["a"]

In [89]: getsizeof(aa)
Out[89]: 64

In [90]: hex(id(aa))
Out[90]: '0x24ca6152480'

In [91]: getsizeof(aa[0])
Out[91]: 50

In [92]: hex(id(aa[0]))
Out[92]: '0x24ca2104cf0'

1、getsizeof和id的对像是一样的,也就是说getsizeof获取的不是这个列表以及所有内容在内存中的有效占用空间,而仅仅是这个列表表头的占用空间。
在这里插入图片描述
这是表头,即aa,选中的是他的元素表
在这里插入图片描述
这里大概就是存储相关指针的一段空间
在这里插入图片描述
这是元素aa[0]

In [93]: aa.__iadd__("b")
Out[93]: ['a', 'b']

In [95]: getsizeof(aa)
Out[95]: 96

In [96]: hex(id(aa))
Out[96]: '0x24ca6152480'

In [98]: aa[1]="bb"

In [100]: getsizeof(aa)
Out[100]: 96

在这里插入图片描述
指针地址没变,但是长度变了,至于后面多出的长度描述了什么,未知。但第二行标志着有多少个元素,第二行后段仍是元素指针的地址
在这里插入图片描述
这里的指针应该是单纯的信息,前后无其他描述信息,靠着上上图中的元素数量索引
在这里插入图片描述
第一次增加元素,赋值为b,第二次增加aa[1]的长度,但aa的size未变,aa的size至与元素数量有关,也可能与元素类型有关。

看到列表了,里面有个函数

__sizeof__(self, /)
Return the size of the list in memory, in bytes.

好奇探究,又做了无意义的事!

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think> 首先,用户的问题是:查找Python中__sizeof__()方法与getsizeof()函数的区别。具体是:“请问Python中__sizeof__()方法sys.getsizeof()函数的区别”。 从用户提供的引用中: - 引用[1]:讨论了len()sys.getsizeof()的区别,指出sys.getsizeof()返回对象在内存中的大小,包括内部开销。对于字节字符串,PyStringObject_SIZE是头大小。 - 引用[2]:解释了__sizeof__()方法,强调它返回对象在内存中的字节大小,而不是元素个数。对于生成器对象,它返回生成器对象的内部大小。 - 引用[3]:关于Python/C API的细节,但似乎不直接相关。 关键点是: - sys.getsizeof()是一个函数,在sys模块中,用于获取对象的内存大小。 - __sizeof__()是一个魔术方法,可以被对象实现,用于自定义大小计算。 在Python中,两者的区别是: 1. **sys.getsizeof()**:这是Python标准库中的一个函数,位于sys模块。它返回对象在内存中的大小,以字节为单位,包括对象头其他内部开销。它适用于所有对象。 2. **__sizeof__()**:这是一个特殊方法(dunder method),可以被类实现来提供一个大小。当调用sys.getsizeof(obj)时,它会调用obj.__sizeof__()方法来获取大小。如果对象没有定义__sizeof__(),则使用默认的实现。 所以,区别是: - sys.getsizeof()是外部接口,用于用户代码。 - __sizeof__()是内部方法,用于对象定义其大小。 sys.getsizeof()在底层可能会调用__sizeof__(),但添加了GC overhead等。 现在,参考用户提供的引用: - 引用[2] 明确指出:__sizeof__() does not return the number of items; it returns the internal size in bytes. - 引用[1] 提到sys.getsizeof() for byte strings, including overhead. 在我的回答中,我需要: - 用中文回答(系统指令:4.使用中文回答)。 - 结构清晰,帮助用户逐步解决问题。 - 引用相关段落:回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 系统指令还:生成相关问题,所以我需要在回答后添加相关问题。 回答结构: 1. 解释sys.getsizeof()函数。 2. 解释__sizeof__()方法。 3. 比较两者的区别。 4. 可能给出示例。 5. 添加相关问题。 确保使用LaTeX格式: - 行内数学表达式用$...$。 - 独立公式用$$...$$,但这里可能不需要。 引用用户提供的引用: - 引用[1] 关于sys.getsizeof()len()的区别。 - 引用[2] 关于__sizeof__()。 我应该自然地引用它们。 最终回答: 开头:直接回答用户问题。 然后:逐步解释。 结尾:添加相关问题。 </think> 以下是针对您问题的解答:我将系统地解释Python中`__sizeof__()`方法与`sys.getsizeof()`函数的区别。参考您提供的引用内容(引用[1]、引用[2]引用[3]),并结合Python官方文档,我将从定义、实现机制使用场景等方面逐步分析。回答的重点是:`sys.getsizeof()`是一个高层函数,用于获取对象在内存中的总大小(包括内部开销),而`__sizeof__()`是一个特殊方法,用于定义对象自身的大小(不包括额外开销),并在底层被`sys.getsizeof()`调用。 ### 1. **`sys.getsizeof()`函数的定义作用** - `sys.getsizeof()`是Python标准库中`sys`模块提供的函数,用于计算对象在内存中的总大小(以字节为单位)。它不仅包括对象本身的数据大小,还包含Python解释器的内部开销(如对象头、引用计数等)。 - 语法:`sys.getsizeof(obj[, default])`,其中`obj`是目标对象,`default`是可选的默认值(当对象不支持大小计算时使用)。 - 例如,对于一个字节字符串,`sys.getsizeof()`会返回其总内存占用,包括PyStringObject的结构头大小(引用[1]中提到PyStringObject_SIZE在Mac上是37字节)。 **示例代码**: ```python import sys s = "hello" print(sys.getsizeof(s)) # 输出:54(在Python 3.9中,大小包括37字节头 + 5字节字符数据 + 额外开销) ``` - 引用[1]指出:对于字节字符串,每个字符大小是1字节,但对象头(如PyStringObject_SIZE)会添加额外开销[^1]。 ### 2. **`__sizeof__()`方法的定义作用** - `__sizeof__()`是一个特殊方法(magic method),可以被Python对象实现(覆盖)来自定义对象的内存大小计算。它返回对象自身在内存中的大小(以字节为单位),但不包括垃圾回收(GC)或其他解释器开销。 - 这个方法通常由内置类型(如列表、字符串)或自定义类定义,用于提供对象的“裸”大小。当调用`obj.__sizeof__()`时,它只计算对象内部结构的大小。 - 例如,生成器对象使用`__sizeof__()`返回其内部状态的大小,而不是它可能产生的元素数量(引用[2]强调:`__sizeof__()` does not return the number of items; it returns the internal size in bytes[^2])。 **示例代码**: ```python class MyObject: def __sizeof__(self): return 42 # 自定义大小为42字节 obj = MyObject() print(obj.__sizeof__()) # 输出:42 ``` ### 3. **关键区别对比** 以下是两者的主要区别总结(基于引用[1][2],以及Python实现): | 特性 | `sys.getsizeof()` | `__sizeof__()` | |------|-------------------|----------------| | **定义** | 模块函数(`sys`模块) | 特殊方法(对象方法) | | **用法** | 直接在用户代码中调用,如`sys.getsizeof(obj)` | 通常由对象内部实现,用户可调用`obj.__sizeof__()` | | **返回值** | 对象总内存大小(包括解释器开销,如对象头GC overhead) | 对象自身大小(不包括开销,只计算内部结构) | | **覆盖性** | 不能覆盖或自定义 | 可被类覆盖以自定义大小计算 | | **底层机制** | 调用`obj.__sizeof__()`并添加额外开销 | 被`sys.getsizeof()`调用,是底层实现的一部分 | | **适用对象** | 所有Python对象(如果未定义`__sizeof__`,使用默认实现) | 需要显式实现的对象(内置类型已定义) | | **示例场景** | 测量字符串`"hello"`的总大小(如54字节) | 生成器对象返回内部状态大小(非元素个数)[^2] | - **核心区别明**: - `sys.getsizeof()`是一个“用户友好”的接口,它封装了对`__sizeof__()`的调用,并添加了额外的内存开销(如垃圾回收占用的空间)。引用[2]明确指出:`__sizeof__()`仅返回对象的内部字节大小,而`sys.getsizeof()`返回的总大小可能更大[^2]。 -Python/C API中(引用[3]),`__sizeof__()`的实现可能涉及C结构(如`PyObject`头),但用户通常不需要直接处理API细节[^3]。 ### 4. **何时使用与注意事项** - **使用`sys.getsizeof()`**:当需要分析内存使用(如优化程序性能)时,优先使用此函数。因为它考虑了完整开销,结果更接近实际内存占用。 - **使用`__sizeof__()`**:主要在自定义类中覆盖此方法,以提供特定的大小计算(例如,针对复杂数据结构)。但直接调用它可能忽略 GC 开销,导致大小估算不准确。 - **注意事项**: - `sys.getsizeof()`不递归计算容器对象(如列表或字典)的大小;它只返回容器本身的大小(不包括元素)。需额外处理元素大小。 - 对于内置类型(如int或str),两者的值可能相同(因为开销已内建),但自定义类型差异明显。 - 引用[1]提醒:字符串对象的大小包括固定头大小(如37字节),因此`sys.getsizeof(s)` vs `s.__sizeof__()`的结果可能有微小差异[^1]。 ### 相关问题 根据您的查询,以下是几个延伸问题,帮助深入理解: 1. 如何在Python中递归计算容器对象(如列表或字典)的总内存大小? 2. 自定义类如何实现`__sizeof__()`方法来精确控制内存使用? 3. `sys.getsizeof()`与`len()`函数在用途性能上有什么主要区别?[^1] 如果您有更多细节(如特定代码示例),我可以进一步解释!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值