Python如何在内部存储datetime?

Python如何在内部存储datetime?,python,c,datetime,memory,cpython,Python,C,Datetime,Memory,Cpython,我发现这似乎是正确的文件,但我需要一些帮助,因为C不是我的强项 >>> import datetime >>> import sys >>> d = datetime.datetime.now() >>> sys.getsizeof(d) 48 >>> d = datetime.datetime(2018, 12, 31, 23, 59, 59, 123) >>> sys.getsizeo

我发现这似乎是正确的文件,但我需要一些帮助,因为C不是我的强项

>>> import datetime
>>> import sys
>>> d = datetime.datetime.now()
>>> sys.getsizeof(d)
48
>>> d = datetime.datetime(2018, 12, 31, 23, 59, 59, 123)
>>> sys.getsizeof(d)
48
因此,一个不知道时区的datetime对象需要48字节。查看
PyDateTime\u-DateTimeType
,它似乎是
PyDateTime\u-DateType
PyDateTime\u-TimeType
。也可以
\u PyDateTime\u BaseTime

通过查看代码,我的印象是,在
YYYY-mm-dd HH:mm:ss
中,每个字段都存储了一个组件,这意味着:

  • 年份:例如int(例如
    int16\t
    将为16位)
  • 月份:例如
    int8\u t
  • 日期:例如
    int8\t
  • 小时:例如
    int8\u t
  • 分钟:例如
    int8\u t
  • 第二:例如
    int8\u t
  • 微秒:例如
    uint16\u t
但这将是2*16+5*8=72位=9字节,而不是Python告诉我的48字节

我对datetime内部结构的假设哪里错了?我如何在代码中看到这一点


(我想这可能在Python实现之间有所不同——如果是这样,请关注cPython)

您缺少了一个关键部分:实际的datetime结构定义,它位于。这里也有重要的评论。以下是一些关键摘录:

/*字段被压缩成连续的字节,每个字节都被视为无符号和
*big-endian,除非另有说明:
*
*字节偏移量
*0年2字节,1-9999
*2个月1字节,1-12
*3天1字节,1-31
*4小时1字节,0-23
*5分钟1字节,0-59
*6秒1字节,0-59
*7秒3字节,0-999999
* 10
*/
...
/*年、月、日、时、分、秒和秒的字节数*/
#定义_PyDateTime_DATETIME_DATASIZE 10
...
/*datetime和time类型具有哈希代码和可选的tzinfo成员,
*当且仅当hastzinfo为true时显示。
*/
#定义_PyTZINFO_HEAD\
皮尤头\
Py_hash_t hashcode\
char hastzinfo;/*布尔标志*/
...
/*所有datetime对象都是PyDateTime\u DateTimeType,但可以是
*也有两种分配方式,就像上面的时间对象一样。此外
*普通日期类型是datetime的基类,因此它还必须具有
*hastzinfo成员(尽管它在那里未使用)。
*/
...
#定义_PyDateTime_DATETIMEHEAD\
_皮兹乌头\
无符号字符数据[_PyDateTime_DATETIME_DATASIZE];
类型定义结构
{
_PyDateTime\u日期时间头
}_PyDateTime_BaseDateTime;/*hastzinfo错误*/
类型定义结构
{
_PyDateTime\u日期时间头
无符号字符折叠;
PyObject*tzinfo;
}PyDateTime_DateTime;/*hastzinfo-true*/
您看到的48字节计数分解如下:

  • 8字节引用计数
  • 8字节型指针
  • 8字节缓存哈希
  • 1字节“hastzinfo”标志
  • 7字节填充
  • 包含日期时间数据的10字节手动压缩
    char[10]
  • 6字节填充

当然,这是所有实现细节。在不同的Python实现、不同的CPython版本、32位CPython构建或CPython调试构建(当CPython使用定义的Py_跟踪_引用编译时,PyObject_头中有额外的内容)上可能会有所不同。

请注意
打印(sys.getsizeof(d.year));打印(sys.getsizeof(d.month));打印(sys.getsizeof(d.day));打印(sys.getsizeof(d.hour));打印(sys.getsizeof(d.minute));打印(sys.getsizeof(d.second));打印(sys.getsizeof(d.microsecond))
打印
28
七次,并且
28*7
196
请注意,您正在计算位(2 int16 ts=2*16)而不是字节(int16 t=2字节)。字节,这是10字节。但是python对象有开销,最小大小似乎至少为28字节,有时更大,具体取决于对象。不过我没有做过那么多的调查。
usecond:3字节
可能是打字错误吗?哪种类型有3个字节?我只看到一些是2字节的,一些是4字节的。@MartinThoma:datetime数据的字节是手动打包在
char[10]
中的,因此不需要3字节类型。