GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Expose PyFloat_AsDouble at Python level: operator.as_float? · Issue #84978 · python/cpython

Expose PyFloat_AsDouble at Python level: operator.as_float? #84978

New issue
Copy link
New issue
Copy link
Closed
Closed
Expose PyFloat_AsDouble at Python level: operator.as_float?#84978
Copy link
Labels
3.11only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement

Description

@mdickinson
mdickinson
opened on May 28, 2020
Issue body actions
BPO 40801
Nosy @mdickinson, @zware, @serhiy-storchaka
PRs
  • bpo-40801: Add operator.as_float #20481
  • gh-84978: Add float.from_number() and complex.from_number() #26827
  • 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 = None
    created_at = <Date 2020-05-28.09:23:06.760>
    labels = ['type-feature', '3.11']
    title = 'Expose PyFloat_AsDouble at Python level: operator.as_float?'
    updated_at = <Date 2021-06-21.12:00:00.034>
    user = 'https://github.com/mdickinson'

    bugs.python.org fields:

    activity = <Date 2021-06-21.12:00:00.034>
    actor = 'serhiy.storchaka'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = []
    creation = <Date 2020-05-28.09:23:06.760>
    creator = 'mark.dickinson'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 40801
    keywords = ['patch']
    message_count = 11.0
    messages = ['370181', '370189', '370233', '370244', '370247', '370253', '370255', '370258', '370259', '370286', '396234']
    nosy_count = 3.0
    nosy_names = ['mark.dickinson', 'zach.ware', 'serhiy.storchaka']
    pr_nums = ['20481', '26827']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue40801'
    versions = ['Python 3.11']

    Linked PRs

    • gh-84978: expose __float__ dunder method as as_float #110460

    Activity

    Next
    1. mdickinson commented on May 28, 2020

      @mdickinson
      mdickinson
      on May 28, 2020
      MemberAuthor
      More actions

      Motivation
      ----------

      Various pieces of Python need to do a duck-typed conversion of an arbitrary float-like object to a float (or a C double) for computation. The math module is the most obvious example - most math-module functions that accept a float also accept float-like things, like np.float32 and Decimal - but it's not the only place that this is needed.

      This conversion is easy at C level, being encapsulated in a single function call: PyFloat_AsDouble. (Plus a PyFloat_FromDouble if you want to go back to Python space, of course.)

      But: it's surprisingly awkward to get an equivalent effect in pure Python code. Options are:

      1. Do an explicit type check to exclude str, bytes and bytearray, and then call the float constructor. But the extra type check is ugly and potentially not future-proof.

      2. Call type(obj).__float__(obj). But this has several problems: __float__ can return an instance of a float subclass rather than a strict float, and then it's hard to convert to an actual float. And in more recent versions of Python, this no longer matches PyFloat_AsDouble because it doesn't account for objects that provide __index__ but not __float__. And calling dunder methods directly should rarely be the Right Way To Do It.

      3. Use the implicit ability of the math module to do this, for example using math.copysign(obj, obj). This works! But it's not a clear expression of the intent.

      This has bitten me in Real Code (TM), where I've needed a way to convert an arbitrary float-like thing to a float, ideally following the same rules that Python uses. And also ideally in such a way that my own code doesn't have to change if Python updates its rules, as for example it did recently to allow things with an __index__ to be considered float-like.

      Proposal
      --------

      Add a new operator function "operator.as_float" which matches Python's duck-typed acceptance of float-like things, in the same way that the existing operator.index matches Python's implicit acceptance of int-like things in various APIs that expect integers.

      Internally, "operator.as_float" would simply call PyFloat_AsDouble followed by PyFloat_FromDouble (possibly with a fast path to pass objects of exact type float through directly).

      Related: bpo-17576.

    2. mdickinson
      added
      3.10 (EOL)end of lifeend of life
      type-featureA feature request or enhancementA feature request or enhancement
      on May 28, 2020
    3. mdickinson
      changed the title [-]Expose PyFloat_ToDouble at Python level: operator.to_float?[/-] [+]Expose PyFloat_ToDouble at Python level: operator.as_float?[/+] on May 28, 2020
    4. mdickinson
      changed the title [-]Expose PyFloat_ToDouble at Python level: operator.to_float?[/-] [+]Expose PyFloat_ToDouble at Python level: operator.as_float?[/+] on May 28, 2020
    5. mdickinson commented on May 28, 2020

      @mdickinson
      mdickinson
      on May 28, 2020
      MemberAuthor
      More actions

      Proof of concept in #64680

    6. zware commented on May 28, 2020

      @zware
      zware
      on May 28, 2020
      Member
      More actions

      operator seems a slightly odd place for this. My naive expectation would be that float(floatlike_obj) should do what you want, but it seems that's not the case (too permissive of input types?). So then, what about an alternate constructor on the float object, float.from_floatlike(obj)? This could be implemented as effectively:

      class float:
          @classmethod
          def from_floatlike(cls, obj):
              return cls(PyFloat_FromDouble(PyFloat_AsDouble(obj)))

      which would work to get an instance of any float subclass after a round-trip through a double. I have no idea whether that's actually useful, though :)

    7. mdickinson commented on May 28, 2020

      @mdickinson
      mdickinson
      on May 28, 2020
      MemberAuthor
      More actions

      operator seems a slightly odd place for this.

      Yes, it's not ideal. It's by analogy with operator.index, which provides the equivalent duck-typing for integers, and calls __index__. Similarly, operator.as_float is primarily there to call __float__, except that now that PyFloat_AsDouble also makes use of __index__, it'll call that, too.

      My other thought was putting this in math, since it's what the math module is already doing implicitly to most inputs.

      An alternative float constructor could work. Though we then run into the messy question of what it should do for float subclasses ...

    8. mdickinson commented on May 28, 2020

      @mdickinson
      mdickinson
      on May 28, 2020
      MemberAuthor
      More actions

      On naming, maybe float.from_number or float.from_numeric?

    9. serhiy-storchaka commented on May 28, 2020

      @serhiy-storchaka
      serhiy-storchaka
      on May 28, 2020
      Member
      More actions

      I think an alternative constructor is the best option. Some time ago I proposed to add more alternative constructors: https://mail.python.org/archives/list/[email protected]/thread/5JKQMIC6EUVCD7IBWMRHY7DRTTNSBOWG/

    10. serhiy-storchaka
      changed the title [-]Expose PyFloat_ToDouble at Python level: operator.as_float?[/-] [+]Expose PyFloat_AsDouble at Python level: operator.as_float?[/+] on May 28, 2020
    11. serhiy-storchaka
      changed the title [-]Expose PyFloat_ToDouble at Python level: operator.as_float?[/-] [+]Expose PyFloat_AsDouble at Python level: operator.as_float?[/+] on May 28, 2020
    12. serhiy-storchaka commented on May 28, 2020

      @serhiy-storchaka
      serhiy-storchaka
      on May 28, 2020
      Member
      More actions

      The problem with the roundtrip PyFloat_FromDouble(PyFloat_AsDouble(obj)) is that (in contrary to PyNumber_Index()) it is lossy. Converting Decimal, Fraction, float128 to float before using it in expression can lead to loss of precision.

      So such conversion looks to me less useful than operator.index().

    13. 1 remaining item

    14. mdickinson commented on May 28, 2020

      @mdickinson
      mdickinson
      on May 28, 2020
      MemberAuthor
      More actions

      Converting Decimal, Fraction, float128 to float before using it in expression can lead to loss of precision.

      My experience is that this loss of precision is hardly ever a practical problem in the real world of scientific development; in practice floating-point numbers are almost universally IEEE 754 doubles (perhaps sometimes single-precision in large datasets, like seismic SEG-Y files; occasionally IBM format hex floats; but IEEE 754 doubles are by far the majority). It's very rare to be using float128 or Decimal or Fraction in practice for scientific data.

      That's not to say that people outside that world won't be using these things, but there's a big ecosystem where float64 is pretty much all you need.

    15. mdickinson commented on May 29, 2020

      @mdickinson
      mdickinson
      on May 29, 2020
      MemberAuthor
      More actions

      I started a python-ideas thread: https://mail.python.org/archives/list/[email protected]/thread/3YGNHGWZOU5AIBS3A52CAHPJJLY7J2CS/

    16. serhiy-storchaka commented on Jun 21, 2021

      @serhiy-storchaka
      serhiy-storchaka
      on Jun 21, 2021
      Member
      More actions

      PR 26827 is a draft for float.from_number() and complex.from_number().

    17. serhiy-storchaka
      added
      3.11only security fixesonly security fixes
      and removed
      3.10 (EOL)end of lifeend of life
      on Jun 21, 2021
    18. ezio-melotti
      transferred this issue fromon Apr 10, 2022
    19. skirpichev commented on Oct 6, 2023

      @skirpichev
      skirpichev
      on Oct 6, 2023
      Member
      More actions
      1. Call type(obj).__float__(obj). But this has several problems: __float__ can return an instance of a float subclass

      Since 3.7 it was deprecated (#71170) and maybe it's time to remove this (#109311).

      So, it's not an issue in that part.

      calling dunder methods directly should rarely be the Right Way To Do It.

      Then why not export obj.__float__() as operator.as_float. Same for obj.__complex__() (as_complex?) or obj.__int__() (as_int?) - all should return an appropriate type.

      Perhaps, a different constructor could be more discoverable option. But I don't see why we can't expose mentioned above dunder methods just as for the __index__. Naming? (i.e. operator.as_float vs operator.float)

    20. skirpichev
      added a commit that references this issue on Oct 6, 2023

      pythongh-84978: expose __float__ dunder method as as_float

      6dfb6ec
    21. iritkatriel
      added
      interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
      on Nov 28, 2023
    22. serhiy-storchaka
      added a commit that references this issue on Jul 15, 2024

      gh-84978: Add float.from_number() and complex.from_number() (GH-26827)

      94bee45
    23. estyxx
      added a commit that references this issue on Jul 17, 2024

      pythongh-84978: Add float.from_number() and complex.from_number() (py…

      07ed42b
    24. skirpichev commented on Sep 19, 2024

      @skirpichev
      skirpichev
      on Sep 19, 2024
      Member
      More actions

      @serhiy-storchaka, probably this can be closed?

    25. serhiy-storchaka
      closed this as completedon Sep 19, 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

      3.11only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancementA feature request or enhancement

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        You are visitor 01402503 — GeezerVison does not store the pages you look up.
        Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.