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

Reply via email to