Consider the following discussion / feature in Python3.9: https://bugs.python.org/issue24416
In short, it was decided that the result of datetime.date.isocalendar
would be changed to a namedtuple
instead of tuple
.
Now, I can see the benefit in doing that, but they also decided “to pickle” the new object (datetime.IsoCalendarDate
) as a tuple:
https://github.com/python/cpython/commit/1b97b9b0ad9a2ff8eb5c8f2e2e7c2aec1d13a330#diff-2a8962dcecb109859cedd81ddc5729bea57d156e0947cb8413f99781a0860fd1R1214
So my question is, why did they make it so that creating the object directly, and “pickling-and-unpickling” the object require slightly different flows?
For example:
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)
Results in:
$ 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'
This inconsistency looks unstable to me. Does it happen in other places in the language?
Advertisement
Answer
I guess, as suggested by Batman comment in this answer:
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. (…)
And unfortunately, this is exactly the case (intentionally!) as we can read in the code of 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),))
So it seems that, for some reason, the inconsequential approach was taken intentionally but I am not aware of (m)any similar situations in Python code.
I think you can raise it as a bug. Maybe the rationale to keep IsoCalendarDate
private from the pickle
perspective should get revisited.