• 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=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$>

    --- 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=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

    --- 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 <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

    --- 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 <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

    --- 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)