“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 <pythonl...@danceswithmice.info> Date: Sunday, February 5, 2023 at 2:54 PM To: Weatherby,Gerard <gweathe...@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....@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