<p dir="auto">version: 1.13.3</p>
<p dir="auto">Example:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; junk, inv = numpy.unique([], return_inverse=True)
&gt;&gt;&gt; print(inv)"><pre class="notranslate"><code class="notranslate">&gt;&gt;&gt; junk, inv = numpy.unique([], return_inverse=True)
&gt;&gt;&gt; print(inv)
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="array([], dtype=bool)"><pre class="notranslate"><code class="notranslate">array([], dtype=bool)
</code></pre></div>
<p dir="auto">The documentation says numpy.unique shall return indices; the sudden change of type is surprising at best.</p>
<p dir="auto">Hello,</p>
<p dir="auto">Obviously, this issue is related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="17810532" data-permission-text="Title is private" data-url="https://github.com/numpy/numpy/issues/3588" data-hovercard-type="issue" data-hovercard-url="/numpy/numpy/issues/3588/hovercard" href="https://github.com/numpy/numpy/issues/3588">#3588</a>. However I give here a more accurate (hopefully) description of the bug and some hints regarding where things go wrong.</p>
<p dir="auto">Here is a sample code producing the problem:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy
import pickle

a = numpy.ma.array([1.0, 2.0], dtype=object)
pickle.loads(pickle.dumps(a))"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span>
<span class="pl-k">import</span> <span class="pl-s1">pickle</span>

<span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">numpy</span>.<span class="pl-s1">ma</span>.<span class="pl-en">array</span>([<span class="pl-c1">1.0</span>, <span class="pl-c1">2.0</span>], <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">object</span>)
<span class="pl-s1">pickle</span>.<span class="pl-en">loads</span>(<span class="pl-s1">pickle</span>.<span class="pl-en">dumps</span>(<span class="pl-s1">a</span>))</pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="TypeError                                 Traceback (most recent call last)
&lt;ipython-input-31-7fbb1ec321e5&gt; in &lt;module&gt;()
      3 
      4 a = numpy.ma.array([1.0, 2.0], dtype=object)
----&gt; 5 pickle.loads(pickle.dumps(a))

/opt/rh/python27/root/usr/lib64/python2.7/pickle.pyc in loads(str)
   1380 def loads(str):
   1381     file = StringIO(str)
-&gt; 1382     return Unpickler(file).load()
   1383 
   1384 # Doctest

/opt/rh/python27/root/usr/lib64/python2.7/pickle.pyc in load(self)
    856             while 1:
    857                 key = read(1)
--&gt; 858                 dispatch[key](self)
    859         except _Stop, stopinst:
    860             return stopinst.value

/opt/rh/python27/root/usr/lib64/python2.7/pickle.pyc in load_build(self)
   1215         setstate = getattr(inst, &quot;__setstate__&quot;, None)
   1216         if setstate:
-&gt; 1217             setstate(state)
   1218             return
   1219         slotstate = None

/home/amignon/mypython27/lib/python2.7/site-packages/numpy/ma/core.pyc in __setstate__(self, state)
   5867         &quot;&quot;&quot;
   5868         (_, shp, typ, isf, raw, msk, flv) = state
-&gt; 5869         super(MaskedArray, self).__setstate__((shp, typ, isf, raw))
   5870         self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk))
   5871         self.fill_value = flv

TypeError: object pickle not returning list"><pre class="notranslate"><code class="notranslate">TypeError                                 Traceback (most recent call last)
&lt;ipython-input-31-7fbb1ec321e5&gt; in &lt;module&gt;()
      3 
      4 a = numpy.ma.array([1.0, 2.0], dtype=object)
----&gt; 5 pickle.loads(pickle.dumps(a))

/opt/rh/python27/root/usr/lib64/python2.7/pickle.pyc in loads(str)
   1380 def loads(str):
   1381     file = StringIO(str)
-&gt; 1382     return Unpickler(file).load()
   1383 
   1384 # Doctest

/opt/rh/python27/root/usr/lib64/python2.7/pickle.pyc in load(self)
    856             while 1:
    857                 key = read(1)
--&gt; 858                 dispatch[key](self)
    859         except _Stop, stopinst:
    860             return stopinst.value

/opt/rh/python27/root/usr/lib64/python2.7/pickle.pyc in load_build(self)
   1215         setstate = getattr(inst, "__setstate__", None)
   1216         if setstate:
-&gt; 1217             setstate(state)
   1218             return
   1219         slotstate = None

/home/amignon/mypython27/lib/python2.7/site-packages/numpy/ma/core.pyc in __setstate__(self, state)
   5867         """
   5868         (_, shp, typ, isf, raw, msk, flv) = state
-&gt; 5869         super(MaskedArray, self).__setstate__((shp, typ, isf, raw))
   5870         self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk))
   5871         self.fill_value = flv

TypeError: object pickle not returning list
</code></pre></div>
<p dir="auto">Basically, I create a masked array with a <code class="notranslate">dtype=object</code> and an exception is raised when the <code class="notranslate">__setstate__</code> method from <code class="notranslate">ndarray</code> is called which corresponds to the code in  <code class="notranslate">/numpy/core/src/multiarray/methods.c</code> at <a href="https://github.com/numpy/numpy/blob/6790bf80c4833cada74a41a85cff339118ef48ca/numpy/core/src/multiarray/methods.c#L1676">line 1676</a>.</p>
<div class="highlight highlight-source-c notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="    if (PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
        if (!PyList_Check(rawdata)) {
            PyErr_SetString(PyExc_TypeError,
                            &quot;object pickle not returning list&quot;);
            return NULL;
        }
    }
    else {
        Py_INCREF(rawdata);
"><pre class="notranslate">    <span class="pl-k">if</span> (<span class="pl-en">PyDataType_FLAGCHK</span>(<span class="pl-s1">typecode</span>, <span class="pl-c1">NPY_LIST_PICKLE</span>)) {
        <span class="pl-k">if</span> (!<span class="pl-en">PyList_Check</span>(<span class="pl-s1">rawdata</span>)) {
            <span class="pl-en">PyErr_SetString</span>(<span class="pl-s1">PyExc_TypeError</span>,
                            <span class="pl-s">"object pickle not returning list"</span>);
            <span class="pl-k">return</span> <span class="pl-c1">NULL</span>;
        }
    }
    <span class="pl-k">else</span> {
        <span class="pl-en">Py_INCREF</span>(<span class="pl-s1">rawdata</span>);</pre></div>
<p dir="auto">From what I understand the source of the problem occurs in the same file at line <a href="https://github.com/numpy/numpy/blob/6790bf80c4833cada74a41a85cff339118ef48ca/numpy/core/src/multiarray/methods.c#L1598">1598</a> when the flag <code class="notranslate">NPY_LIST_PICKLE</code> is tested in the <code class="notranslate">__reduce__</code> method of <code class="notranslate">ndarray</code> (<code class="notranslate">array_reduce</code> function):</p>
<div class="highlight highlight-source-c notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="    if (PyDataType_FLAGCHK(PyArray_DESCR(self), NPY_LIST_PICKLE)) {
        thestr = _getlist_pkl(self);
    }
    else {
        thestr = PyArray_ToString(self, NPY_ANYORDER);
    }"><pre class="notranslate">    <span class="pl-k">if</span> (<span class="pl-en">PyDataType_FLAGCHK</span>(<span class="pl-en">PyArray_DESCR</span>(<span class="pl-s1">self</span>), <span class="pl-c1">NPY_LIST_PICKLE</span>)) {
        <span class="pl-s1">thestr</span> <span class="pl-c1">=</span> <span class="pl-en">_getlist_pkl</span>(<span class="pl-s1">self</span>);
    }
    <span class="pl-k">else</span> {
        <span class="pl-s1">thestr</span> <span class="pl-c1">=</span> <span class="pl-en">PyArray_ToString</span>(<span class="pl-s1">self</span>, <span class="pl-c1">NPY_ANYORDER</span>);
    }</pre></div>
<p dir="auto">For some reason it is not recognised as having to be pickled as list as expected when it is called from the <code class="notranslate">__getstate__</code> method of <code class="notranslate">MaskedArray</code> in <code class="notranslate">numpy/ma/core.py</code> at line <a href="https://github.com/numpy/numpy/blob/6790bf80c4833cada74a41a85cff339118ef48ca/numpy/ma/core.py#L5869">5869</a></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="    def __getstate__(self):
        &quot;&quot;&quot;Return the internal state of the masked array, for pickling
        purposes.
        &quot;&quot;&quot;
        cf = 'CF'[self.flags.fnc]
        data_state = super(MaskedArray, self).__reduce__()[2]
        return data_state + (getmaskarray(self).tobytes(cf), self._fill_value)"><pre class="notranslate">    <span class="pl-k">def</span> <span class="pl-en">__getstate__</span>(<span class="pl-s1">self</span>):
        <span class="pl-s">"""Return the internal state of the masked array, for pickling</span>
<span class="pl-s">        purposes.</span>
<span class="pl-s">        """</span>
        <span class="pl-s1">cf</span> <span class="pl-c1">=</span> <span class="pl-s">'CF'</span>[<span class="pl-s1">self</span>.<span class="pl-s1">flags</span>.<span class="pl-s1">fnc</span>]
        <span class="pl-s1">data_state</span> <span class="pl-c1">=</span> <span class="pl-en">super</span>(<span class="pl-v">MaskedArray</span>, <span class="pl-s1">self</span>).<span class="pl-en">__reduce__</span>()[<span class="pl-c1">2</span>]
        <span class="pl-k">return</span> <span class="pl-s1">data_state</span> <span class="pl-c1">+</span> (<span class="pl-en">getmaskarray</span>(<span class="pl-s1">self</span>).<span class="pl-en">tobytes</span>(<span class="pl-s1">cf</span>), <span class="pl-s1">self</span>.<span class="pl-s1">_fill_value</span>)</pre></div>
<p dir="auto">This weird behaviour is confirmed by trying this python code:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy
import pickle

a = numpy.ma.array([1.0, 2.0], dtype=object)
print a.__getstate__()[:-2] # The two last elements correspond to the mask
print super(np.ma.MaskedArray, a).__reduce__()[2] # Used internally in __getstate__"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span>
<span class="pl-k">import</span> <span class="pl-s1">pickle</span>

<span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">numpy</span>.<span class="pl-s1">ma</span>.<span class="pl-en">array</span>([<span class="pl-c1">1.0</span>, <span class="pl-c1">2.0</span>], <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">object</span>)
<span class="pl-k">print</span> <span class="pl-s1">a</span>.<span class="pl-en">__getstate__</span>()[:<span class="pl-c1">-</span><span class="pl-c1">2</span>] <span class="pl-c"># The two last elements correspond to the mask</span>
<span class="pl-k">print</span> <span class="pl-en">super</span>(<span class="pl-s1">np</span>.<span class="pl-s1">ma</span>.<span class="pl-v">MaskedArray</span>, <span class="pl-s1">a</span>).<span class="pl-en">__reduce__</span>()[<span class="pl-c1">2</span>] <span class="pl-c"># Used internally in __getstate__</span></pre></div>
<p dir="auto">Which gives:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="(1, (2,), dtype('O'), False, 'X\xca\x84\x01\x00\x00\x00\x00p\xca\x84\x01\x00\x00\x00\x00')
(1, (2,), dtype('O'), False, [1.0, 2.0])"><pre class="notranslate"><code class="notranslate">(1, (2,), dtype('O'), False, 'X\xca\x84\x01\x00\x00\x00\x00p\xca\x84\x01\x00\x00\x00\x00')
(1, (2,), dtype('O'), False, [1.0, 2.0])
</code></pre></div>
<p dir="auto">This is weird since the second line uses the same <code class="notranslate">__reduce__</code> method from <code class="notranslate">ndarray</code>  as in the <code class="notranslate">__getstate__</code> method of <code class="notranslate">MaskedArray</code>.</p>
<p dir="auto">I've not been able to go further.</p>
<p dir="auto">Hoping this helps</p>