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.