Mailing List Archive

Typing Number, PyCharm
Do we have a typing type-hint for numbers yet?


Often wanting to combine int and float, discovered that an application
was doing a walk-through with/for uses three numeric types. Was
intrigued to note variance, in that the code-set features two different
methods for typing, in this situation:

def func( value ):
...using value...

where value may be an integer, a floating-point value, or a
complex-number (but not decimal-type).
NB code snippets from memory (cf copy-paste)


Method 1 (possibly older code):-

from typing import Union
...
def fun( value:Union[ int, float, complex ] ):


Method 2:-

def fun( value:int|float|complex ):


Pondering this, realised could use an alias to de-clutter the
function-definition/signature:

Method 3:-

number_type = int|float|complex
...
def fun( value:number_type ):


If it was important to have type consistency within the union, eg
argument and return, could go for:

Method 4:-

from typing import TypeVar
number_type = TypeVar( 'number_type', int, float, complex )
...
def fun( value:number_type ):


Then remembered the way we'd code an execution-time check for this using
isinstance():

Method 5:-

from numbers import Number
...
def fun( value:Number ):


Each of these will execute correctly.

All cause PyCharm to object if I try to call the fun(ction) with a
string parameter - and execute an exception, as expected.


Accepting all the others, am curious as to why PyCharm objects to Method
5 with "Expected type 'SupportsFloat | SupportsComplex | complex |
SupportsIndex', got 'Number' instead? - yet still highlights the
erroneous string parameter but none of the 'legal' data-types?

As soon as a list (in this case types) reaches three, my aged-eyes start
to think de-cluttering is a good idea!

Do you know of another way to attack this/more properly?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: Typing Number, PyCharm [ In reply to ]
dn,

I?m missing something here. Method 5 seems to work fine in PyCharm. I?m interpreting your statement as:

from fractions import Fraction
from numbers import Number


def double(value: Number):
if isinstance(value, Number):
# noinspection PyTypeChecker
return 2 * value
raise ValueError(f"{value} of {type(value)} is not a Number")


print(double(7))
print(double(7.2))
print(double(complex(3.2, 4.5)))
print(double(Fraction(7, 8)))
# print(double("7")) PyCharm properly complains


From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of dn via Python-list <python-list@python.org>
Date: Saturday, February 4, 2023 at 9:32 PM
To: 'Python' <python-list@python.org>
Subject: Typing Number, PyCharm
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

Do we have a typing type-hint for numbers yet?


Often wanting to combine int and float, discovered that an application
was doing a walk-through with/for uses three numeric types. Was
intrigued to note variance, in that the code-set features two different
methods for typing, in this situation:

def func( value ):
...using value...

where value may be an integer, a floating-point value, or a
complex-number (but not decimal-type).
NB code snippets from memory (cf copy-paste)


Method 1 (possibly older code):-

from typing import Union
...
def fun( value:Union[ int, float, complex ] ):


Method 2:-

def fun( value:int|float|complex ):


Pondering this, realised could use an alias to de-clutter the
function-definition/signature:

Method 3:-

number_type = int|float|complex
...
def fun( value:number_type ):


If it was important to have type consistency within the union, eg
argument and return, could go for:

Method 4:-

from typing import TypeVar
number_type = TypeVar( 'number_type', int, float, complex )
...
def fun( value:number_type ):


Then remembered the way we'd code an execution-time check for this using
isinstance():

Method 5:-

from numbers import Number
...
def fun( value:Number ):


Each of these will execute correctly.

All cause PyCharm to object if I try to call the fun(ction) with a
string parameter - and execute an exception, as expected.


Accepting all the others, am curious as to why PyCharm objects to Method
5 with "Expected type 'SupportsFloat | SupportsComplex | complex |
SupportsIndex', got 'Number' instead? - yet still highlights the
erroneous string parameter but none of the 'legal' data-types?

As soon as a list (in this case types) reaches three, my aged-eyes start
to think de-cluttering is a good idea!

Do you know of another way to attack this/more properly?

--
Regards,
=dn
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Typing Number, PyCharm [ In reply to ]
No @Gerard, YOU weren't missing anything: since posting, have upgraded
PyCharm to 2022.3.2 and the complaints about 'Method 5' have
disappeared. Evidently a PyCharm issue!

Which alters the top-line question to: is numbers.Number the preferred
type-hint when multiple numeric types are to be accepted?

PS no Decimal(s) nor Fraction(s) in my situation, but may be worth
adding to a wider discussion...


On 06/02/2023 04.03, Weatherby,Gerard wrote:
> dn,
>
> I’m missing something here. Method 5 seems to work fine in PyCharm. I’m
> interpreting your statement as:
>
> from fractions import Fraction
> from numbers import Number
>
>
> def double(value: Number):
> if isinstance(value, Number):
> /# noinspection PyTypeChecker
> /return 2 * value
> raise ValueError(f"{value}of {type(value)}is not a Number")
>
>
> print(double(7))
> print(double(7.2))
> print(double(complex(3.2, 4.5)))
> print(double(Fraction(7, 8)))
> /# print(double("7")) PyCharm properly complains/
>
> *From: *Python-list <python-list-bounces+gweatherby=uchc.edu@python.org>
> on behalf of dn via Python-list <python-list@python.org>
> *Date: *Saturday, February 4, 2023 at 9:32 PM
> *To: *'Python' <python-list@python.org>
> *Subject: *Typing Number, PyCharm
>
> *** Attention: This is an external email. Use caution responding,
> opening attachments or clicking on links. ***
>
> Do we have a typing type-hint for numbers yet?
>
>
> Often wanting to combine int and float, discovered that an application
> was doing a walk-through with/for uses three numeric types. Was
> intrigued to note variance, in that the code-set features two different
> methods for typing, in this situation:
>
> def func( value ):
>      ...using value...
>
> where value may be an integer, a floating-point value, or a
> complex-number (but not decimal-type).
> NB code snippets from memory (cf copy-paste)
>
>
> Method 1 (possibly older code):-
>
> from typing import Union
> ...
> def fun( value:Union[ int, float, complex ] ):
>
>
> Method 2:-
>
> def fun( value:int|float|complex  ):
>
>
> Pondering this, realised could use an alias to de-clutter the
> function-definition/signature:
>
> Method 3:-
>
> number_type = int|float|complex
> ...
> def fun( value:number_type  ):
>
>
> If it was important to have type consistency within the union, eg
> argument and return, could go for:
>
> Method 4:-
>
> from typing import TypeVar
> number_type = TypeVar( 'number_type', int, float, complex )
> ...
> def fun( value:number_type  ):
>
>
> Then remembered the way we'd code an execution-time check for this using
> isinstance():
>
> Method 5:-
>
> from numbers import Number
> ...
> def fun( value:Number  ):
>
>
> Each of these will execute correctly.
>
> All cause PyCharm to object if I try to call the fun(ction) with a
> string parameter - and execute an exception, as expected.
>
>
> Accepting all the others, am curious as to why PyCharm objects to Method
> 5 with "Expected type 'SupportsFloat | SupportsComplex | complex |
> SupportsIndex', got 'Number' instead? - yet still highlights the
> erroneous string parameter but none of the 'legal' data-types?
>
> As soon as a list (in this case types) reaches three, my aged-eyes start
> to think de-cluttering is a good idea!
>
> Do you know of another way to attack this/more properly?
>
> --
> Regards,
> =dn
> --
> https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$ <https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$>
>

--
Regards,
=dn

--
https://mail.python.org/mailman/listinfo/python-list
Re: Typing Number, PyCharm [ In reply to ]
?is numbers.Number the preferred type-hint when multiple numeric types are to be accepted??

I don?t know.

On the one hand, it is a well-known type, so it should be recognizable to users of an API. On the other hand, Number is entirely abstract, so it doesn?t provide useful type checking for the implementation; I had to add # noinspection PyTypeChecker to 2 * value to keep PyCharm from complaining. Additionally, it does not include the Decimal type. Interestingly, It was added in 2007 in anticipation of ?if and when overloading based on types is added to the language.? This now seems unlikely to happen. ( https://peps.python.org/pep-3141/#rationale )

On the other hand, a specific type alias is clearer to type checkers and possibly to the user of an API?

Experimenting, it appears isinstance checks of Type Aliases don?t work before 3.10, and its TypeAlias construct. That is:

Numeric = Union[int, float, complex, Fraction]


def double(value: Numeric):
if isinstance(value, Numeric):
return 2 * value
raise ValueError(f"{value} of {type(value)} is not Numeric")
Fails but

Numeric : TypeAlias = Union[int, float, complex, Fraction]


def double(value: Numeric):
if isinstance(value, Numeric):
return 2 * value
raise ValueError(f"{value} of {type(value)} is not Numeric")

works (>= 3.10)


From: dn <PythonList@DancesWithMice.info>
Date: Sunday, February 5, 2023 at 2:54 PM
To: Weatherby,Gerard <gweatherby@uchc.edu>, 'Python' <python-list@python.org>
Subject: Re: Typing Number, PyCharm
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

No @Gerard, YOU weren't missing anything: since posting, have upgraded
PyCharm to 2022.3.2 and the complaints about 'Method 5' have
disappeared. Evidently a PyCharm issue!

Which alters the top-line question to: is numbers.Number the preferred
type-hint when multiple numeric types are to be accepted?

PS no Decimal(s) nor Fraction(s) in my situation, but may be worth
adding to a wider discussion...


On 06/02/2023 04.03, Weatherby,Gerard wrote:
> dn,
>
> I?m missing something here. Method 5 seems to work fine in PyCharm. I?m
> interpreting your statement as:
>
> from fractions import Fraction
> from numbers import Number
>
>
> def double(value: Number):
> if isinstance(value, Number):
> /# noinspection PyTypeChecker
> /return 2 * value
> raise ValueError(f"{value}of {type(value)}is not a Number")
>
>
> print(double(7))
> print(double(7.2))
> print(double(complex(3.2, 4.5)))
> print(double(Fraction(7, 8)))
> /# print(double("7")) PyCharm properly complains/
>
> *From: *Python-list <python-list-bounces+gweatherby=uchc.edu@python.org>
> on behalf of dn via Python-list <python-list@python.org>
> *Date: *Saturday, February 4, 2023 at 9:32 PM
> *To: *'Python' <python-list@python.org>
> *Subject: *Typing Number, PyCharm
>
> *** Attention: This is an external email. Use caution responding,
> opening attachments or clicking on links. ***
>
> Do we have a typing type-hint for numbers yet?
>
>
> Often wanting to combine int and float, discovered that an application
> was doing a walk-through with/for uses three numeric types. Was
> intrigued to note variance, in that the code-set features two different
> methods for typing, in this situation:
>
> def func( value ):
> ...using value...
>
> where value may be an integer, a floating-point value, or a
> complex-number (but not decimal-type).
> NB code snippets from memory (cf copy-paste)
>
>
> Method 1 (possibly older code):-
>
> from typing import Union
> ...
> def fun( value:Union[ int, float, complex ] ):
>
>
> Method 2:-
>
> def fun( value:int|float|complex ):
>
>
> Pondering this, realised could use an alias to de-clutter the
> function-definition/signature:
>
> Method 3:-
>
> number_type = int|float|complex
> ...
> def fun( value:number_type ):
>
>
> If it was important to have type consistency within the union, eg
> argument and return, could go for:
>
> Method 4:-
>
> from typing import TypeVar
> number_type = TypeVar( 'number_type', int, float, complex )
> ...
> def fun( value:number_type ):
>
>
> Then remembered the way we'd code an execution-time check for this using
> isinstance():
>
> Method 5:-
>
> from numbers import Number
> ...
> def fun( value:Number ):
>
>
> Each of these will execute correctly.
>
> All cause PyCharm to object if I try to call the fun(ction) with a
> string parameter - and execute an exception, as expected.
>
>
> Accepting all the others, am curious as to why PyCharm objects to Method
> 5 with "Expected type 'SupportsFloat | SupportsComplex | complex |
> SupportsIndex', got 'Number' instead? - yet still highlights the
> erroneous string parameter but none of the 'legal' data-types?
>
> As soon as a list (in this case types) reaches three, my aged-eyes start
> to think de-cluttering is a good idea!
>
> Do you know of another way to attack this/more properly?
>
> --
> Regards,
> =dn
> --
> https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$> <https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!gqIbcK1zaXmlo5y6741fRwcBUcDfxPNkiA4Jy_NHr9nEno2HaBGZYMuitXeivWrGwTJtds01pHdFfiY_Y5bnmsq_NQ$>
>

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: Typing Number, PyCharm [ In reply to ]
On Mon, 2023-02-06 at 12:11 +0000, Weatherby,Gerard wrote:

> On the one hand, it is a well-known type, so it should be
> recognizable to users of an API. On the other hand, Number is
> entirely abstract, so it doesn’t provide useful type checking for the
> implementation; I had to add # noinspection PyTypeChecker to 2 *
> value to keep PyCharm from complaining. Additionally, it does not
> include the Decimal type.

Hmm...

Python 3.10.9 (main, Dec 19 2022, 17:35:49) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from numbers import Number
>>> from decimal import Decimal as D
>>> isinstance(D("1.0"), Number)
True

--
https://mail.python.org/mailman/listinfo/python-list
Re: Typing Number, PyCharm [ In reply to ]
Yeah, I?m confused.
?The Decimal Type<https://peps.python.org/pep-3141/#the-decimal-type>

After consultation with its authors it has been decided that the Decimal type should not at this time be made part of the numeric tower.? https://peps.python.org/pep-3141/#the-decimal-type

And the Decimal definition I?m finding says:
class Decimal(object):

yet

print(issubclass(Decimal,Number))

returns True.




From: Paul Bryan <pbryan@anode.ca>
Date: Monday, February 6, 2023 at 9:25 AM
To: Weatherby,Gerard <gweatherby@uchc.edu>, dn <PythonList@DancesWithMice.info>, 'Python' <python-list@python.org>
Subject: Re: Typing Number, PyCharm
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***
On Mon, 2023-02-06 at 12:11 +0000, Weatherby,Gerard wrote:

On the one hand, it is a well-known type, so it should be recognizable to users of an API. On the other hand, Number is entirely abstract, so it doesn?t provide useful type checking for the implementation; I had to add # noinspection PyTypeChecker to 2 * value to keep PyCharm from complaining. Additionally, it does not include the Decimal type.

Hmm...

Python 3.10.9 (main, Dec 19 2022, 17:35:49) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from numbers import Number
>>> from decimal import Decimal as D
>>> isinstance(D("1.0"), Number)
True

--
https://mail.python.org/mailman/listinfo/python-list