You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It seems that in python 2.7 I can do a = {np.ma.masked: 'AAA'} while in python3 this code throws TypeError: unhashable type: 'MaskedConstant' (numpy 1.8. in both cases).
np.ma.masked is an instance of the np.ma.MaskedArray class and therefore is not hashable in Python 3 for the same reason why all instances of np.ma.MaskedArray or even np.ndarray are not hashable, their contents can change over time.
How can you change the contents of np.ma.masked? Easy, just modify the _data or _mask attributes. But please don't actually do this, bad things may result.
@ahaldane Correct, a = {np.ma.masked: 'AAA'} should not work in either Python 2 or 3 since np.ma.masked is mutable.
From a git bisect is looks like PR #5326 fixed the old broken behavior where np.ma.masked was hashable and allowed to be a dictionary key. After this fix the example will raise a TypeError which I think is the correct behavior.
This behavior is not covered by any unit tests, it may be prudent to add tests along the lines of:
Coming back to this because of astropy/astropy#6153 (comment), I still don't understand why np.ma.masked should not be hashable. It is an instance of MaskedConstant, which strongly implies that it is not mutable (even if it earlier derives from MaskedArray). What is the point of naming something a constant if it can be changed?
Indeed if you try to change it via public methods an exception is raised. (I'm not concerned that there is a back-door private attribute, if somebody messes with np.ma.masked in that way then they get what they deserve).
In [7]: np.ma.masked[()] = 10
---------------------------------------------------------------------------
MaskError Traceback (most recent call last)
<ipython-input-7-a4d285aabd96> in <module>()
----> 1 np.ma.masked[()] = 10
/Users/aldcroft/anaconda3/envs/astropy/lib/python3.5/site-packages/numpy/ma/core.py in __setitem__(self, indx, value)
3227 """
3228 if self is masked:
-> 3229 raise MaskError('Cannot alter the masked element.')
3230 _data = self._data
3231 _mask = self._mask
MaskError: Cannot alter the masked element.
Somewhat on-topic: Would it make sense that when an array's flag.writable is set to False, that the array becomes hashable, since it can no longer be modified? (My immediate goal is just to memoize functions that take numpy arrays as inputs.)
That's an interesting idea, but unfortunately doesn't work too well - I can create a read-only view of a writeable array, and the hash will vary with the source array
Activity
jjhelmus commentedon Oct 21, 2015
np.ma.maskedis an instance of thenp.ma.MaskedArrayclass and therefore is not hashable in Python 3 for the same reason why all instances ofnp.ma.MaskedArrayor evennp.ndarrayare not hashable, their contents can change over time.How can you change the contents of
np.ma.masked? Easy, just modify the _data or _mask attributes. But please don't actually do this, bad things may result.ahaldane commentedon Oct 22, 2015
The example
a = {np.ma.masked: 'AAA'}shouldn't work in python2 either, right? It doesn't work on my machine with 1.10.jjhelmus commentedon Oct 22, 2015
@ahaldane Correct,
a = {np.ma.masked: 'AAA'}should not work in either Python 2 or 3 since np.ma.masked is mutable.From a git bisect is looks like PR #5326 fixed the old broken behavior where
np.ma.maskedwas hashable and allowed to be a dictionary key. After this fix the example will raise a TypeError which I think is the correct behavior.This behavior is not covered by any unit tests, it may be prudent to add tests along the lines of:
Such tests might currently fail in Windows due to issue #5647.
taldcroft commentedon Jun 4, 2017
Coming back to this because of astropy/astropy#6153 (comment), I still don't understand why
np.ma.maskedshould not be hashable. It is an instance ofMaskedConstant, which strongly implies that it is not mutable (even if it earlier derives fromMaskedArray). What is the point of naming something a constant if it can be changed?Indeed if you try to change it via public methods an exception is raised. (I'm not concerned that there is a back-door private attribute, if somebody messes with np.ma.masked in that way then they get what they deserve).
eric-wieser commentedon Sep 28, 2017
This no longer works
I can see one argument: it represents an unknown value, and an unknown value has an unknown hash.
mhvk commentedon Sep 28, 2017
but
np.nancan be used as a key. Since we often write<something> is masked, I think it is reasonable for it to be assumed constant and thus hashable.endolith commentedon Aug 3, 2019
Somewhat on-topic: Would it make sense that when an array's
flag.writableis set toFalse, that the array becomes hashable, since it can no longer be modified? (My immediate goal is just to memoize functions that take numpy arrays as inputs.)eric-wieser commentedon Aug 4, 2019
That's an interesting idea, but unfortunately doesn't work too well - I can create a read-only view of a writeable array, and the hash will vary with the source array