Python 3.9: unpickling IsoCalendarDate 数据 returns 一个元组

Python 3.9: unpickling of IsoCalendarDate data returns a tuple

考虑 Python3.9 中的以下讨论/功能: https://bugs.python.org/issue24416

简而言之,决定将 datetime.date.isocalendar 的结果改为 namedtuple 而不是 tuple

现在,我可以看到这样做的好处,但他们还决定将新对象 (datetime.IsoCalendarDate)“腌制”为元组:
https://github.com/python/cpython/commit/1b97b9b0ad9a2ff8eb5c8f2e2e7c2aec1d13a330#diff-2a8962dcecb109859cedd81ddc5729bea57d156e0947cb8413f99781a0860fd1R1214

所以我的问题是,为什么他们要直接创建对象,而“pickling-and-unpickling”对象需要稍微不同的流程?

例如:

import datetime
from pathlib import Path
import pickle



RESULTS_CACHE_PICKLE = Path('cache.pickle')


if RESULTS_CACHE_PICKLE.is_file():
    with open(RESULTS_CACHE_PICKLE, 'rb') as f:
        icd = pickle.load(f)
else:
    icd = datetime.date(2019, 1, 1).isocalendar()
    with open(RESULTS_CACHE_PICKLE, 'wb') as f:
        pickle.dump(icd, f)
        
        
print(icd.year)

结果:

$ python icd_test.py
2019
$ python icd_test.py
Traceback (most recent call last):
  File "icd_test.py", line 19, in <module>
    print(icd.year)
AttributeError: 'tuple' object has no attribute 'year'

这种不一致对我来说看起来不稳定。它是否发生在语言的其他地方?

我猜,正如 蝙蝠侠 中评论的建议:

One is that namedtuple isn't a class, it's a class factory that returns a class, which you in turn use to make instances. (...)

不幸的是,正如我们在 IsoCalendarDate(tuple) class:

的代码中所读到的那样(故意的!)
def __reduce__(self):
    # This code is intended to pickle the object without making the
    # class public. See https://bugs.python.org/msg352381
    return (tuple, (tuple(self),))

所以看来,对于 some reason,这种无关紧要的方法是故意采取的,但我不知道 Python 代码中有 (m) 任何类似情况。

我认为您可以将其作为错误提出。也许应该重新审视从 pickle 的角度保持 IsoCalendarDate 私有的理由。