MCPcopy Create free account
hub / github.com/numpy/numpy / __array_finalize__

Method __array_finalize__

numpy/ma/core.py:2978–3069  ·  view source on GitHub ↗

Finalizes the masked array.

(self, obj)

Source from the content-addressed store, hash-verified

2976 return
2977
2978 def __array_finalize__(self, obj):
2979 """
2980 Finalizes the masked array.
2981
2982 """
2983 # Get main attributes.
2984 self._update_from(obj)
2985
2986 # We have to decide how to initialize self.mask, based on
2987 # obj.mask. This is very difficult. There might be some
2988 # correspondence between the elements in the array we are being
2989 # created from (= obj) and us. Or there might not. This method can
2990 # be called in all kinds of places for all kinds of reasons -- could
2991 # be empty_like, could be slicing, could be a ufunc, could be a view.
2992 # The numpy subclassing interface simply doesn't give us any way
2993 # to know, which means that at best this method will be based on
2994 # guesswork and heuristics. To make things worse, there isn't even any
2995 # clear consensus about what the desired behavior is. For instance,
2996 # most users think that np.empty_like(marr) -- which goes via this
2997 # method -- should return a masked array with an empty mask (see
2998 # gh-3404 and linked discussions), but others disagree, and they have
2999 # existing code which depends on empty_like returning an array that
3000 # matches the input mask.
3001 #
3002 # Historically our algorithm was: if the template object mask had the
3003 # same *number of elements* as us, then we used *it's mask object
3004 # itself* as our mask, so that writes to us would also write to the
3005 # original array. This is horribly broken in multiple ways.
3006 #
3007 # Now what we do instead is, if the template object mask has the same
3008 # number of elements as us, and we do not have the same base pointer
3009 # as the template object (b/c views like arr[...] should keep the same
3010 # mask), then we make a copy of the template object mask and use
3011 # that. This is also horribly broken but somewhat less so. Maybe.
3012 if isinstance(obj, ndarray):
3013 # XX: This looks like a bug -- shouldn't it check self.dtype
3014 # instead?
3015 if obj.dtype.names is not None:
3016 _mask = getmaskarray(obj)
3017 else:
3018 _mask = getmask(obj)
3019
3020 # If self and obj point to exactly the same data, then probably
3021 # self is a simple view of obj (e.g., self = obj[...]), so they
3022 # should share the same mask. (This isn't 100% reliable, e.g. self
3023 # could be the first row of obj, or have strange strides, but as a
3024 # heuristic it's not bad.) In all other cases, we make a copy of
3025 # the mask, so that future modifications to 'self' do not end up
3026 # side-effecting 'obj' as well.
3027 if (_mask is not nomask and obj.__array_interface__["data"][0]
3028 != self.__array_interface__["data"][0]):
3029 # We should make a copy. But we could get here via astype,
3030 # in which case the mask might need a new dtype as well
3031 # (e.g., changing to or from a structured dtype), and the
3032 # order could have changed. So, change the mask type if
3033 # needed and use astype instead of copy.
3034 if self.dtype == obj.dtype:
3035 _mask_dtype = _mask.dtype

Callers 1

__array_finalize__Method · 0.45

Calls 7

_update_fromMethod · 0.95
getmaskarrayFunction · 0.85
getmaskFunction · 0.85
make_mask_descrFunction · 0.85
_check_fill_valueFunction · 0.85
astypeMethod · 0.80
viewMethod · 0.45

Tested by

no test coverage detected