On Thu, Jun 27, 2024 at 3:48 PM Aaron Meurer <asmeu...@gmail.com> wrote: > > Apparently the reason this happens is that True, False, and None are > compared using 'is' in structural pattern matching (see > https://peps.python.org/pep-0634/#literal-patterns). > > There's no way NumPy could avoid this. First off, Python won't even > let you subclass bool: > > >>> class mybool(bool): > ... pass > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: type 'bool' is not an acceptable base type > > np.bool_ objects *do* compare equal to bool: > > >>> type(np.array(1) > 0) > <class 'numpy.bool_'> > >>> (np.array(1) > 0) == True > True > > but that doesn't matter because True is specifically special cased in > structural pattern matching. > > The workaround is to use np.True_ and np.False_ in your pattern > > >>> match a > 1: > ... case np.True_ | np.False_: > ... print('python float') > ... case _: > ... print('Huh?: numpy float') > python float > > Fortunately, since these compare equal to Python bool, this will also > work even if a > 1 is a normal True or False: > > >>> a = 1 > >>> import numpy as np > ... a = np.float64(1) > ... assert isinstance(a, float) > ... match a > 1: > ... case np.True_ | np.False_: > ... print('python float') > ... case _: > ... print('Huh?: numpy float') > python float
Typo. This should have just been: >>> a = 1 >>> match a > 1: ... case np.True_ | np.False_: ... print("matches python bool") ... case _: ... print("doesn't match") matches python bool Aaron Meurer > > Aaron Meurer > > On Thu, Jun 27, 2024 at 3:33 PM Stefano Miccoli via NumPy-Discussion > <numpy-discussion@python.org> wrote: > > > > It is well known that ‘np.bool' is not interchangeable with python ‘bool’, > > and in fact 'issubclass(np.bool, bool)’ is false. > > > > On the contrary, numpy floats are subclassing python > > floats—'issubclass(np.float64, float) is true—so I’m wondering if the fact > > that scalar comparison returns a np.bool breaks the Liskov substitution > > principle. In fact ’(np.float64(1) > 0) is True’ is unexpectedly false. > > > > I was hit by this behaviour because in python structural pattern matching, > > the ‘a > 1’ subject will not match neither ’True’ or ‘False’ if ‘a' is a > > numpy scalar: In this short example > > > > import numpy as np > > a = np.float64(1) > > assert isinstance(a, float) > > match a > 1: > > case True | False: > > print('python float') > > case _: > > print('Huh?: numpy float’) > > > > the default clause is matched. If we set instead ‘a = float(1)’, the first > > clause will be matched. The surprise factor is quite high here, in my > > opinion. > > (Let me add that ‘True', ‘False', ‘None' are special in python structural > > pattern matching, because they are matched by identity and not by equality.) > > > > I’m not sure if this behaviour can be avoided, or if we have to live with > > the fact that numpy floats are to be kept well contained and never mixed > > with python floats. > > > > Stefano_______________________________________________ > > NumPy-Discussion mailing list -- numpy-discussion@python.org > > To unsubscribe send an email to numpy-discussion-le...@python.org > > https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ > > Member address: asmeu...@gmail.com _______________________________________________ NumPy-Discussion mailing list -- numpy-discussion@python.org To unsubscribe send an email to numpy-discussion-le...@python.org https://mail.python.org/mailman3/lists/numpy-discussion.python.org/ Member address: arch...@mail-archive.com