-
-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Description
Describe the issue:
I'm not certain whether this is an issue with the implementation or the documentation but it seems that the two are not in sync. From the documentation of __array_finalize__ for derived np.ndarray types we find the following statement:
One sees that the super call, which goes to ndarray.__new__, passes __array_finalize__ the new object, of our own class (self) as well as the object from which the view has been taken (obj). As you can see from the output above, the self is always a newly created instance of our subclass, and the type of obj differs for the three instance creation methods:
When called from the explicit constructor, obj is None
When called from view casting, obj can be an instance of any subclass of ndarray, including our own.
When called in new-from-template, obj is another instance of our own subclass, that we might use to update the new self instance.
In the provided example case we have a case where a new object of the derived class has been created, __new__ has not been called and yet __array_finalize__ has been called with obj == None
As far as I can see this happens because internally the new array is allocated with tp_alloc and tp_new is never called but then __array_finalize__ is being called explicitly in the C code.
Note that the code example in the documentation shows the same pattern and therefore exhibits the same problem.
Reproduce the code example:
import numpy as np
class A(np.ndarray):
def __new__(cls, shape, dtype):
array = np.array(shape, dtype=dtype)
out = array.view(cls)
out.custom_attribute = 1
return out
def __array_finalize__(self, obj):
if obj is None:
return
self.custom_attribute = 2
a = A(shape=(2, 3), dtype=np.uint8)
print(a.custom_attribute)
b = np.unpackbits(a)
print(b.custom_attribute)Error message:
1
Traceback (most recent call last):
File "/temp/numpy_bug_report/test.py", line 24, in <module>
print(b.custom_attribute)
^^^^^^^^^^^^^^^^^^
AttributeError: 'A' object has no attribute 'custom_attribute'Python and NumPy Versions:
2.4.0
3.14.2 | packaged by conda-forge | (main, Dec 6 2025, 11:21:58) [GCC 14.3.0]
Runtime Environment:
[{'numpy_version': '2.4.0',
'python': '3.14.2 | packaged by conda-forge | (main, Dec 6 2025, 11:21:58) '
'[GCC 14.3.0]',
'uname': uname_result(system='Linux', node='host', release='3.10.0-1160.80.1.1.el7.dug.x86_64', version='#1 SMP Tue Nov 22 09:43:42 GMT 2022', machine='x86_64')},
{'simd_extensions': {'baseline': ['X86_V2'],
'found': ['X86_V3'],
'not_found': ['X86_V4', 'AVX512_ICL', 'AVX512_SPR']}},
{'ignore_floating_point_errors_in_matmul': False},
{'architecture': 'Haswell',
'filepath': '/envs/numpy_bugreport/lib/libopenblasp-r0.3.30.so',
'internal_api': 'openblas',
'num_threads': 40,
'prefix': 'libopenblas',
'threading_layer': 'pthreads',
'user_api': 'blas',
'version': '0.3.30'}]
How does this issue affect you or how did you find it:
This pattern of a derived np.ndarray class can for example be found in the devito project: https://github.com/devitocodes/devito/blob/f020eb1616cbe8ccd864b416649b5db1e0a0f3ef/devito/data/data.py#L99