Skip to content

int and set subclass __sizeof__ under-reports the instance dictionary pointer #101266

Closed
@ionite34

Description

@ionite34

Bug report

Most built-in types, when subclassed, will have a __sizeof__ that is 8 (pointer size) larger than the parent object, due to having an instance dictionary.

class UserFloat(float): pass
assert UserFloat().__sizeof__() - (0.0).__sizeof__() == 8

class UserTuple(tuple): pass
assert UserTuple().__sizeof__() - ().__sizeof__() == 8

class UserList(list): pass
assert UserList().__sizeof__() - [].__sizeof__() == 8

class UserDict(dict): pass
assert UserDict().__sizeof__() - {}.__sizeof__() == 8

This is unexpectedly, not the case for int and set, which exactly match the original __sizeof__

class UserSet(set): pass
print(UserSet().__sizeof__(), set().__sizeof__())  # 200 200

class UserInt(int): pass
print(UserInt().__sizeof__(), (0).__sizeof__())  # 24 24

As a result this makes __dictoffset__ usages incorrect as well

from ctypes import py_object

class UserTuple(tuple): pass

x = UserTuple()
x.a = 5
print(x.__dict__)
>> {'a': 5}
py_object.from_address(id(x) + x.__sizeof__() + UserTuple.__dictoffset__)
>> py_object({'a': 5})
from ctypes import py_object

class UserInt(int): pass

x = UserInt()
x.a = 5
print(x.__dict__)
>> {'a': 5}
py_object.from_address(id(x) + x.__sizeof__() + UserInt.__dictoffset__)
>> py_object(<NULL>)

Your environment

  • CPython versions tested on: 3.11, 3.12.0a3

Linked PRs

Metadata

Metadata

Assignees

Labels

type-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions