Matching a dict subclass without the __reduce__ method does not load member attributes

I need to make sure that it dictcan only accept certain types of objects as values. It also needs to be selected. Here is my first attempt:

import pickle

class TypedDict(dict):
    _dict_type = None

    def __init__(self, dict_type, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._dict_type = dict_type

    def __setitem__(self, key, value):
        if not isinstance(value, self._dict_type):
            raise TypeError('Wrong type')
        super().__setitem__(key, value)

If I test it with the following code (python 3.5)

my_dict = TypedDict(int)
my_dict['foo'] = 98

with open('out.pkl', 'wb') as fin:
    pickle.dump(my_dict, fin)

with open('out.pkl', 'rb') as fin:
    out = pickle.load(fin)

I get an error: TypeError: isinstance() arg 2 must be a type or tuple of types.
It does not seem to load the correct value for _dict_typeand instead uses the default value None.
Also, it looks like it is protocol dependent, as if it is working correctly withprotocol=0

However, if I redefine the method __reduce__and just call super, everything works magically.

def __reduce__(self):
    return super().__reduce__()

How is this possible? Shouldn't there be equivalents of two classes (without __reduce__)? What am I missing?

+4
1

? ( __reduce__)? ?

: __reduce__ ( !), . , __reduce__ __reduce__ ( , )!

dict , . , __setitem__, . __setitem__ _dict_type. , None,

TypeError: isinstance() arg 2 must be a type or tuple of types

, TypedDict __reduce__, -. __setitem__, :

my_dict = TypedDict(int)

with open('out.pkl', 'wb') as fin:
    pickle.dump(my_dict, fin)

with open('out.pkl', 'rb') as fin:
    out = pickle.load(fin)

print(out._dict_type)   # int

, , __reduce__, dicts, __reduce__ - ( , __reduce__):

>>> d = {1: 1}
>>> dict.__reduce__(d)
TypeError: "can't pickle dict objects"

>>> d = TypedDict(int)
>>> dict.__reduce__(d)
(<function copyreg._reconstructor>,
 (__main__.TypedDict, dict, {}),
 {'_dict_type': int})
+1

Source: https://habr.com/ru/post/1686756/


All Articles