@@ -49,13 +49,9 @@ class ApproxNumpyBase(ApproxBase):
49
49
"""
50
50
Perform approximate comparisons for numpy arrays.
51
51
52
- This class should not be used directly. Instead, it should be used to make
53
- a subclass that also inherits from `np.ndarray`, e.g.::
54
-
55
- import numpy as np
56
- ApproxNumpy = type('ApproxNumpy', (ApproxNumpyBase, np.ndarray), {})
57
-
58
- This bizarre invocation is necessary because the object doing the
52
+ This class should not be used directly. Instead, the `inherit_ndarray()`
53
+ class method should be used to make a subclass that also inherits from
54
+ `np.ndarray`. This indirection is necessary because the object doing the
59
55
approximate comparison must inherit from `np.ndarray`, or it will only work
60
56
on the left side of the `==` operator. But importing numpy is relatively
61
57
expensive, so we also want to avoid that unless we actually have a numpy
@@ -81,6 +77,18 @@ class ApproxNumpyBase(ApproxBase):
81
77
it appears on.
82
78
"""
83
79
80
+ subclass = None
81
+
82
+ @classmethod
83
+ def inherit_ndarray (cls ):
84
+ import numpy as np
85
+ assert not isinstance (cls , np .ndarray )
86
+
87
+ if cls .subclass is None :
88
+ cls .subclass = type ('ApproxNumpy' , (ApproxNumpyBase , np .ndarray ), {})
89
+
90
+ return cls .subclass
91
+
84
92
def __new__ (cls , expected , rel = None , abs = None , nan_ok = False ):
85
93
"""
86
94
Numpy uses __new__ (rather than __init__) to initialize objects.
@@ -416,8 +424,7 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
416
424
if _is_numpy_array (expected ):
417
425
# Create the delegate class on the fly. This allow us to inherit from
418
426
# ``np.ndarray`` while still not importing numpy unless we need to.
419
- import numpy as np
420
- cls = type ('ApproxNumpy' , (ApproxNumpyBase , np .ndarray ), {})
427
+ cls = ApproxNumpyBase .inherit_ndarray ()
421
428
elif isinstance (expected , Mapping ):
422
429
cls = ApproxMapping
423
430
elif isinstance (expected , Sequence ) and not isinstance (expected , String ):
0 commit comments