为什么不同的类占用相同的内存空间?

4
为什么如果一个变量有另一个变量参考,它不会占用更多的内存?
class Foo():
  a = 1
  b = 1

class Bar():
  a = 1

import sys

foo = Foo()
print(sys.getsizeof(foo))  # 56
bar = Bar()
print(sys.getsizeof(bar))  # 56

2
这些方法并没有保存在对象本身中,如果保存了,那么所有实例中都会重复存在。 - azro
1
方法不是与对象一起存储的,而是与对象的类型一起存储的。 - chepner
1
也就是说,每个对象都维护着对其类型的引用,并且方法是通过该类型访问的。foo.bar 实际上只是 Foo.bar.__get__(foo, Foo) 的简写形式。 - chepner
这并不奇怪:https://zh.wikipedia.org/wiki/%E8%99%9A%E6%8B%9F%E6%96%B9%E6%B3%95%E8%A1%A8 - fuglede
1个回答

6

首先,方法是与对象的类型一起存储的,而不是对象本身。

然而,你会注意到如果你要求类的大小,它们也是相等的。

>>> sys.getsizeof(Foo)
1064
>>> sys.getsizeof(Bar)
1064

每个类对象都有一个 __dict__ 属性,它存储对其方法和其他属性的引用。
>>> Foo.__dict__['why_does_this_not_use_take_memory']
<function Foo.why_does_this_not_use_take_memory at 0x103609ef0>

然而,sys.getsizeof不会递归到该dict中; 它只返回class对象本身使用的内存,不包括通过class及其属性可访问的对象。
每个方法都是类属性。 不用过多涉及描述符协议,通常类似于foo.why_does_this_not_use_take_memory实际上只是缩写形式。
Foo.why_does_this_not_use_take_memory.__get__(foo, Foo)

也就是说,获取了 function 属性值,但然后调用它的 __get__ 方法返回一个特定于 foomethod 对象。这个 method 实际上只是一个围绕该函数的包装器,当被调用时,将 foo 和自己的参数传递给 Foo.why_does_this_not_use_take_memory(这是 self 绑定到 foo 的方式)。


1
除了这个出色的答案,我建议使用Pympler来获取有关Python对象内存大小的详细信息。链接中提供了示例用法。关于对象内存使用和会计类内存大小的更详细的博客文章在这里 - agtoever

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接