问题描述
我发现似乎是正确的文件,但我需要一些帮助,因为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
因此,时区不知道的日期时间对象需要48个字节。
查看PyDateTime_DateTimeType
,它似乎是PyDateTime_DateType
和PyDateTime_TimeType
。
也许还_PyDateTime_BaseTime
?
从查看代码,我的印象是YYYY-mm-dd HH:MM:ss
每个字段都存储了一个组件,意思是:
-
年份:例如int(例如
int16_t
将是16位) -
月:例如
int8_t
-
日:例如
int8_t
-
小时:例如
int8_t
-
分钟:例如
int8_t
-
第二:例如
int8_t
-
微秒:例如
uint16_t
但是,这将是2 * 16 + 5 * 8 = 72位= 9字节而不是48字节,因为Python告诉我。
我对datetime内部结构的假设在哪里错了? 我怎么能在代码中看到这个?
(我想这可能在Python实现之间有所不同 - 如果是这样,请关注cPython)
1楼
您错过了图片的关键部分:实际的日期时间结构定义,位于 。 那里也有重要的评论。 以下是一些关键摘录:
/* Fields are packed into successive bytes, each viewed as unsigned and
* big-endian, unless otherwise noted:
*
* byte offset
* 0 year 2 bytes, 1-9999
* 2 month 1 byte, 1-12
* 3 day 1 byte, 1-31
* 4 hour 1 byte, 0-23
* 5 minute 1 byte, 0-59
* 6 second 1 byte, 0-59
* 7 usecond 3 bytes, 0-999999
* 10
*/
...
/* # of bytes for year, month, day, hour, minute, second, and usecond. */
#define _PyDateTime_DATETIME_DATASIZE 10
...
/* The datetime and time types have hashcodes, and an optional tzinfo member,
* present if and only if hastzinfo is true.
*/
#define _PyTZINFO_HEAD \
PyObject_HEAD \
Py_hash_t hashcode; \
char hastzinfo; /* boolean flag */
...
/* All datetime objects are of PyDateTime_DateTimeType, but that can be
* allocated in two ways too, just like for time objects above. In addition,
* the plain date type is a base class for datetime, so it must also have
* a hastzinfo member (although it's unused there).
*/
...
#define _PyDateTime_DATETIMEHEAD \
_PyTZINFO_HEAD \
unsigned char data[_PyDateTime_DATETIME_DATASIZE];
typedef struct
{
_PyDateTime_DATETIMEHEAD
} _PyDateTime_BaseDateTime; /* hastzinfo false */
typedef struct
{
_PyDateTime_DATETIMEHEAD
unsigned char fold;
PyObject *tzinfo;
} PyDateTime_DateTime; /* hastzinfo true */
您看到的48字节计数如下所示:
- 8字节引用计数
- 8字节类型指针
- 8字节缓存哈希
- 1字节“hastzinfo”标志
- 7字节填充
-
包含日期时间数据的10字节手动打包
char[10]
- 6字节填充
当然,这是所有实施细节。 它可能在不同的Python实现,或不同的CPython版本,或32位CPython构建,或CPython调试构建上有所不同(当使用Py_TRACE_REFS定义编译CPython时,PyObject_HEAD中有额外的东西)。