Because plain dict is not adequate for inheritance, I design the following MyDict with UserDict in python standard libraries:
import numpy as np
from collections import UserDict
class MyUserDict(UserDict):
pass
m_dict = {'a': np.arange(2),
'b': np.arange(2)}
m_mydict = MyUserDict(m_dict)
Then I meet a problem. When turning a list of UserDict into numpy array, values in UserDict have lost:
m_dict_array = np.array([m_dict, m_dict])
m_mydict_array = np.array([m_mydict, m_mydict])
print(m_dict_array)
print(m_mydict_array)
""" The output is
[{'a': array([0, 1]), 'b': array([0, 1])}
{'a': array([0, 1]), 'b': array([0, 1])}]
[['a' 'b']
['a' 'b']]
"""
The solution I find is adding __array__() method to MyUserDict:
class MyUserDict(UserDict):
def __array__(self):
# Prevent NumPy from converting to an array of keys
return np.array(self.data, dtype=object)
m_mydict = MyUserDict(m_dict)
m_mydict_array = np.array([m_mydict, m_mydict])
print(m_mydict_array)
This indeed solve my problem. But another problem I quickly realized is that self.data is plain dict and elements in m_mydict_array may be also plain dict. So, I check the type as follows:
print(type(m_mydict_array[0]))
The type is MyUserDict I defined. This is certainly the result I hoped for, but I have no idea why it turned out like this.
How does __array__() work? Why is the type of m_mydict_array[0] not default 'dict'?
dtype=objectmeans (roughly) to use plain Python objects without any conversion. In fact,m_mydict_array[0] is m_mydictis true.np.array([m_mydict, m_mydict])the__array__method is actually invoked, however the resulting array does not contain the return value of__array__but rather the object itself. Changing the return to a dummy array (e.g.np.arange) does in fact change the result completely.