• Typing Number, PyCharm

    From dn@21:1/5 to All on Sun Feb 5 15:30:18 2023
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to All on Sun Feb 5 15:03:23 2023
    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=[email protected]> on behalf of dn via Python-list <[email protected]>
    Date: Saturday, February 4, 2023 at 9:32 PM
    To: 'Python' <[email protected]>
    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$>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Gerard on Mon Feb 6 08:53:37 2023
    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=[email protected]>
    on behalf of dn via Python-list <[email protected]>
    *Date: *Saturday, February 4, 2023 at 9:32 PM
    *To: *'Python' <[email protected]>
    *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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to Gerard on Mon Feb 6 12:11:31 2023
    �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 <[email protected]>
    Date: Sunday, February 5, 2023 at 2:54 PM
    To: Weatherby,Gerard <[email protected]>, 'Python' <[email protected]> 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=[email protected]>
    on behalf of dn via Python-list <[email protected]>
    *Date: *Saturday, February 4, 2023 at 9:32 PM
    *To: *'Python' <[email protected]>
    *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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to All on Mon Feb 6 15:07:31 2023
    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 <[email protected]>
    Date: Monday, February 6, 2023 at 9:25 AM
    To: Weatherby,Gerard <[email protected]>, dn <[email protected]>, 'Python' <[email protected]>
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Bryan@21:1/5 to Gerard on Mon Feb 6 06:25:46 2023
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)