Sitelet https://github.com/python/cpython/issues/68422
Skip to content

Should we define complex.__complex__ and bytes.__bytes__? #68422

Description

@gvanrossum
BPO 24234
Nosy @gvanrossum, @terryjreedy, @mdickinson, @serhiy-storchaka, @ethanhs, @corona10, @gyu-don
PRs
  • bpo-24234: implement complex.__complex__ #27887
  • bpo-24234: Implement bytes.__bytes__ #27901
  • bpo-24234: fix bytes.__bytes__ to not truncate at a zero byte #27902
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2021-08-26.08:47:44.516>
    created_at = <Date 2015-05-18.21:37:35.463>
    labels = ['3.11']
    title = 'Should we define complex.__complex__ and bytes.__bytes__?'
    updated_at = <Date 2021-08-26.08:47:44.516>
    user = 'https://github.com/gvanrossum'

    bugs.python.org fields:

    activity = <Date 2021-08-26.08:47:44.516>
    actor = 'mark.dickinson'
    assignee = 'none'
    closed = True
    closed_date = <Date 2021-08-26.08:47:44.516>
    closer = 'mark.dickinson'
    components = []
    creation = <Date 2015-05-18.21:37:35.463>
    creator = 'gvanrossum'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 24234
    keywords = ['patch']
    message_count = 18.0
    messages = ['243538', '243842', '314623', '314630', '389805', '395471', '395474', '400067', '400068', '400109', '400113', '400114', '400123', '400124', '400126', '400127', '400129', '400326']
    nosy_count = 7.0
    nosy_names = ['gvanrossum', 'terry.reedy', 'mark.dickinson', 'serhiy.storchaka', 'ethan smith', 'corona10', 'gyu-don']
    pr_nums = ['27887', '27901', '27902']
    priority = 'normal'
    resolution = None
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue24234'
    versions = ['Python 3.11']

    Activity

    1. gvanrossum commented on May 18, 2015

      @gvanrossum
      MemberAuthor

      The special methods __complex__ and __bytes__ are not present on the corresponding builtin types. Compare this to __int__ and __float__, which do exist on int and float, respectively. Should we add the eponymous methods to complex and bytes?

      (This came up in the context of PEP-484: python/typing#68 (comment) )

    2. terryjreedy commented on May 22, 2015

      @terryjreedy
      Member

      To my understanding, the presence of int.__int__ and float.__float__ are implementation issues. I presume that float(ob) just calls ob.__float__ without slowing down for an isinstance(ob, float) check. Ditto for int(ob). The processing for complex(args) and bytes(args) are more complex and currently neither call an eponyous method. Would either be improved if it did?

      One difference between int and complex, for instance, that might account for the internal implementation difference is that the second argument of int can only be used with a string first argument, while the second argument of complex cannot be used with a string first argument, and must support multiplication by 1j. So int.__int__(self) does not allow a second parameter and can (and does) just return self.

    3. serhiy-storchaka commented on Mar 29, 2018

      @serhiy-storchaka
      Member

      The difference between __complex__ and __bytes__ on one side, and __int__ and __float__ on other side is that the latter have dedicated type slots while the former are just entries in the type's dict. Thus testing and calling __int__ and __float__ is much faster.

    4. gvanrossum commented on Mar 29, 2018

      @gvanrossum
      MemberAuthor

      It's not necessary for complex() and bytes() to call the special methods if the argument's type is exactly complex or bytes (respectively) -- these cases are already taken care of by the current code. But adding these special methods enables other code to be more regular, without having to test for the special cases.

    5. gyu-don commented on Mar 30, 2021

      gyu-donmannequin
      Mannequin

      Recently, the situation has changed. We should consider this issue again.

      typing.SupportsComplex is an ABC with one abstract method __complex__.
      Thus, isinstance(complex, typing.SupportsComplex) is False.
      typing.SupportsBytes also.

      It is nonsense.

    6. ethanhs commented on Jun 9, 2021

      ethanhsmannequin
      Mannequin

      While I don't think it is nonsense, I do think it would be quite useful to add these. I just submitted PRs to typeshed and numpy adding complex to unions that already had SupportsComplex, because of the lack of __complex__. I'd be happy to work on a PR for this if it would be accepted.

    7. gvanrossum commented on Jun 9, 2021

      @gvanrossum
      MemberAuthor

      Yeah, the more I think about it, the more it looks like we should add the special methods -- even if they won't necessarily be called *if the type is exactly 'complex' or 'bytes'*.

      Now, until we've written and released the code we won't know for sure whether this might break somebody's corner case, so we should play it safe and only do this for 3.11 and make sure it's mentioned in the What's New.

    8. mdickinson commented on Aug 22, 2021

      @mdickinson
      Member

      If the goal is to have isinstance(obj, typing.SupportsComplex) pass for objects that are convertible to complex, then we'll need int.__complex__ and float.__complex__ implementations as well as complex.__complex__.

    9. mdickinson commented on Aug 22, 2021

      @mdickinson
      Member

      [...] we'll need int.__complex__ and float.__complex__ implementations as well as complex.__complex__.

      The real problem here is that the "typing.SupportsComplex" protocol isn't a good match for code that needs to know that a given value x can be treated as though it were a complex number.

      The test that best matches "usable as a complex number" seems to be that type(x) implements at least one of __index__, __float__ or __complex__, or that x is a subclass of complex.

      It looks to me as though the right thing to do here is to just implement complex.__complex__, but not int.__complex__ or float.__complex__. Then at least we can remove the subclass test from the above and express the test purely in terms of special methods: __index__, __float__ and __complex__. And then perhaps it's for the typing module to find a more convenient way to express the union of typing.SupportsIndex, typing.SupportsFloat and typing.SupportsComplex.

    10. gvanrossum commented on Aug 22, 2021

      @gvanrossum
      MemberAuthor

      What about __bytes__?

    11. corona10 commented on Aug 23, 2021

      @corona10
      Member

      @guido

      >>> issubclass(bytes, typing.SupportsBytes)
      False

      IMHO, supporting is reasonable.

    12. gvanrossum commented on Aug 23, 2021

      @gvanrossum
      MemberAuthor

      So let’s add that in a separate PR.

      --Guido (mobile)

    13. serhiy-storchaka commented on Aug 23, 2021

      @serhiy-storchaka
      Member

      Defining complex.__complex__ and bytes.__bytes__ would not solve anything, because

      >>> issubclass(int, SupportsComplex)
      False
      >>> issubclass(float, SupportsComplex)
      False
      >>> issubclass(bytearray, SupportsBytes)
      False
      >>> issubclass(memoryview, SupportsBytes)
      False

      If SupportsComplex and SupportsBytes are just for "has __complex__/bytes method", they are virtually useless. If their meaning is "can be converted to complex/bytes", it is different story, and it should be fixed be adding subclasshooks which check existence of alternate methods (float, __index__, supporting the buffer protocol).

    14. mdickinson commented on Aug 23, 2021

      @mdickinson
      Member

      New changeset 6082bb5 by Mark Dickinson in branch 'main':
      bpo-24234: implement complex.__complex__ (GH-27887)
      6082bb5

    15. corona10 commented on Aug 23, 2021

      @corona10
      Member

      New changeset 24b63c6 by Dong-hee Na in branch 'main':
      bpo-24234: Implement bytes.__bytes__ (GH-27901)
      24b63c6

    16. mdickinson commented on Aug 23, 2021

      @mdickinson
      Member

      If SupportsComplex and SupportsBytes are just for "has __complex__/bytes method", they are virtually useless.

      I agree that "SupportsComplex" isn't directly useful in user-land. I think its main value is as a building block in things like Union[SupportsComplex, SupportsFloat, SupportsIndex].

      For me, the gain from implementing complex.__complex__ is that the test "can be used as a complex number" can now be expressed purely in terms of the protocols offered, without reference to concrete types.

    17. mdickinson commented on Aug 23, 2021

      @mdickinson
      Member

      We've got some buildbot failures; python/issues-test-cpython#27902 should fix them. Apologies for not catching this while reviewing python/issues-test-cpython#27901.

    18. mdickinson commented on Aug 26, 2021

      @mdickinson
      Member

      All done, I think. Closing.

    19. transferred this issue fromon Apr 10, 2022
    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

      3.11only security fixes

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions