Skip to content

Improve pow(fraction.Fraction(), b, modulo) error message #119594

Closed

Description

@wimglenn

Bug report

Bug description:

Fraction.__pow__ does not accept the third argument which pow tries to pass to it:

>>> pow(Fraction(1), 1, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Fraction.__pow__() takes 2 positional arguments but 3 were given

Other number types don't do that, they support it when they can and print an error message if they don't want to, e.g.

>>> pow(Decimal("1"), 1, 1)
Decimal('0')
>>> pow(Decimal('1'), 1.1, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pow() 3rd argument not allowed unless all arguments are integers

I'm not sure what fraction should do, maybe it should just continue not to support it? Or just accept the argument, and then print a better error message if modulo is not None?

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    type-featureA feature request or enhancement
    and removed
    type-bugAn unexpected behavior, bug, or error
    on May 27, 2024
  2. terryjreedy commented on May 27, 2024

    @terryjreedy
    Member

    Fractions.__pow__ should imitate float and Decimal __pow__.

    pow(3.0, 7, 3)
    Traceback (most recent call last):
      File "<pyshell#5>", line 1, in <module>
        pow(3.0, 7, 3)
    TypeError: pow() 3rd argument not allowed unless all arguments are integers
    

    Since the exception type is correct, this should be considered an enhancement rather than bug.

    PR was a bit premature without agreement of what fix should be.

  3. mdickinson commented on May 27, 2024

    @mdickinson
    Member

    Not supporting a modulus was an intentional choice here.

    It's hard to imagine real use-cases would be for supporting the modulus. If m is a positive integer, the collection of integers modulo m has nice arithmetic properties (it's a commutative unital ring), and exponentiation modulo m is a reasonably common operation (e.g., in cryptography). That's no longer true for the collection of fractions modulo m - that set doesn't have an associative multiplication operation, so a power operation is at best ill-defined.

    If we want to change the error message (as @terryjreedy pointed out, the exception type is already the right one), the first thing to try would be to return NotImplemented if a third argument is given. That should work, but the special-casing for __pow__ is messy enough that it might not.

  4. mdickinson commented on May 27, 2024

    @mdickinson
    Member

    That should work, but [...]

    It does. Results of a quick test:

    >>> pow(Fraction(2), 3)
    Fraction(8, 1)
    >>> pow(Fraction(2), 3, 5)
    Traceback (most recent call last):
      File "<python-input-4>", line 1, in <module>
        pow(Fraction(2), 3, 5)
        ~~~^^^^^^^^^^^^^^^^^^^
    TypeError: unsupported operand type(s) for ** or pow(): 'Fraction', 'int', 'int'
  5. changed the title [-]fractions.Fraction.__pow__ can receive 3rd argument from builtin function pow[/-] [+]Improve pow(fraction.Fraction(), b, modulo) error message[/+] on May 29, 2024
  6. added a commit that references this issue on May 29, 2024
  7. added a commit that references this issue on Jul 11, 2024
  8. added a commit that references this issue on Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions