Skip to content

Confusing output from help(math.pi) #104042

Closed as not planned
Closed as not planned

Description

@mfriedenthal

Documentation

Both print(math.pi.__doc__) and print(help(math.pi)) are returning the wrong documentation.

(A clear and concise description of the issue.)
image

This code was executed in Thonny 4.02, Python version 3.10.9.

**Convert a string or number to a floating point number, if possible.
Help on float object:

class float(object)
| float(x=0, /)
|
| Convert a string or number to a floating point number, if possible.**

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    type-bugAn unexpected behavior, bug, or error
    on May 1, 2023
  2. ronaldoussoren commented on May 1, 2023

    @ronaldoussoren
    Contributor

    It might be possible to make this more clear, but this is expected behaviour.

    Help on an instance (such as the floating point number math.pi) shows Help on ... object followed by the help of the class of the object. This makes it easier to show which methods and members are present on an object by way of its class.

  3. AlexWaygood commented on May 1, 2023

    @AlexWaygood
    Member

    math.pi is just an instance of float, and the __doc__ attribute here is providing accurate documentation about the float class in Python. I don't see any way that the behavior can be improved here; it's not possible to set custom docstrings on instances of float.

  4. removed
    type-bugAn unexpected behavior, bug, or error
    docsDocumentation in the Doc dir
    on May 1, 2023
  5. changed the title [-]pi __doc__[/-] [+]Confusing output from `help(math.pi)`[/+] on May 1, 2023
  6. ronaldoussoren commented on May 1, 2023

    @ronaldoussoren
    Contributor

    It might be possible to improve on the generic header to make it clearer that most of the shown help is on the class of the instance. That said, I don't have a proposal and for me the documentation is clear enough.

  7. mfriedenthal commented on May 1, 2023

    @mfriedenthal
    Author
  8. mfriedenthal commented on May 1, 2023

    @mfriedenthal
    Author
  9. AlexWaygood commented on May 1, 2023

    @AlexWaygood
    Member

    Yes, the difference is that math.sqrt is a function object, and it's possible to set custom __doc__ attributes on each separate function object. It's not possible to set custom docstrings on each separate float object in the same way. Changing that would be a major change that might have a performance penalty.

  10. terryjreedy commented on May 1, 2023

    @terryjreedy
    Member

    pi is just a name for the float 3.141592653589793. It happens to be pre-bound in math for convenience. It is otherwise nothing special. help(pi) is the same as help(3.141592653589793) and indeed, the same as help(0.0) or help(394829038029.98989). help` says what one can do with an object, including what attributes one can access, and AFAIK this is the same for all floats.

    help(math) lists first the method attributes and then, after 300 lines, the data attributes.

    DATA
        e = 2.718281828459045
        inf = inf
        nan = nan
        pi = 3.141592653589793
        tau = 6.283185307179586
    

    I believe that both lists are automatically generated by pydoc by getting all attributes and classifying them by a rule.

  11. mfriedenthal commented on May 1, 2023

    @mfriedenthal
    Author
  12. terryjreedy commented on May 1, 2023

    @terryjreedy
    Member

    More helpful in what way? Help receives a binary floating point object that happens to have the decimal representation '3.141592653589793'. It does not know what name(s), if any, have been bound to the object it receives. help is not meant to substitute for reading docs. It is just a reminder.

  13. AlexWaygood commented on May 1, 2023

    @AlexWaygood
    Member

    The output from help() here might be easier to understand for a beginner here if, instead of "Help on float object", the title said "Help on 3.141592653589793, an instance of float"

  14. serhiy-storchaka commented on May 1, 2024

    @serhiy-storchaka
    Member

    The output from help() here might be easier to understand for a beginner here if, instead of "Help on float object", the title said "Help on 3.141592653589793, an instance of float"

    It would be misleading, because what you get is actually the help on float object, not on 3.141592653589793.

    I do not think that we should do anything here and propose to close this issue.

  15. terryjreedy commented on May 1, 2024

    @terryjreedy
    Member

    OP claims that it 'confusing', 'wrong', and 'useless' for help(pi) to return help on class float, but never said whether the claim only applies to 'pi' or to instance names in general, nor what specific or general alternative would be 'better'. We can and have dismissed 'wrong' and 'useless': help should return something different from other object information functions, such as str, repr, type, dir, vars, etc.

    I considered whether the specific response "Help on x object:" should be reworded. After trying various types of objects, I think not, or at least not only this response. When anything other than a non-empty string is passed, the initial line is consistently "Help on :". I think this consistency is good and any discussion of (consistently) changing it, and possibly breaking code, should be a new issue divorced from this 'math.pi'discussion.

  16. skirpichev commented on May 27, 2026

    @skirpichev
    Member

    It's not possible to set custom docstrings on each separate float object in the same way.

    I don't think so. It's easy to create a custom float subclass with a different repr and docstring. In fact, we do something like this in the re module (_NamedIntConstant).

    Changing that would be a major change that might have a performance penalty.

    Hmm, I doubt that someone rely on the fact that pi.__doc__ has some generic value ;-) Hardly changing it's repr will also affect something, though it's more disputable.

    Assuming proposed above solution, performance penalty will come with creation of the module constant. This will affect import timings and so on, not using of constants. IMO, it's not a high price.

    OP claims that it 'confusing', 'wrong', and 'useless' for help(pi) to return help on class float, but never said whether the claim only applies to 'pi' or to instance names in general

    He did:

    Giving documentation of class float is useless to the programmer looking for documentation on pi.

    Apparently, OP want documentation on the module constant, like math.pi. His wishes seems reasonable for me: sometimes you can guess what's it is, just from name, but what about math.tau, for example? Generic documentation for the float class seems at least "useless" in such cases, indeed.

    Of course, you always can look on the sphinx docs for the module. But if it's not optional - this seems as a limitation for me.

    @terryjreedy, can we reopen issue on this ground?

  17. self-assigned this
    on May 27, 2026
  18. serhiy-storchaka commented on May 27, 2026

    @serhiy-storchaka
    Member

    Many code has special fast path for exact float, so using a float subclass will have performance impact. Some code (like marshal) only works with exact floats, so this can be a breaking change. Mixed type binary operations with float subclasses are tricky, this can lead to difficult bugs.

    _NamedIntConstant in the re module does not represent numeric constants, it represents cheap enums, which are also ints. The only reason of using a _NamedIntConstant instead of a raw int is for internal debugging of the re module.

    And I think that changing the class of math.pi is moving in wrong direction. It is a float, it should have the same class like other floats, like atan(1) and exp(1). You can make help('math.pi') showing the specialized help, but don't change the class of math.pi.

  19. skirpichev commented on May 28, 2026

    @skirpichev
    Member

    using a float subclass will have performance impact.

    That discussed in the d.p.o thread: https://discuss.python.org/t/107540. I doubt it will have a big performance effect.

    Some code (like marshal) only works with exact floats, so this can be a breaking change.

    Any other example than marshal?

    You can make help('math.pi') showing the specialized help, but don't change the class of math.pi.

    d.p.o thread has proposal for such mechanism:
    https://discuss.python.org/t/add-a-mixin-class-to-allow-module-constants-with-custom-repr-and-docstrings/107540/2

    Though, this doesn't affect repr. Currently, it's impossible to use provided constant as default values in production code:

    def foo(x=math.e):
        ...
    

    will produce unreadable foo(x=2.718281828459045) signature. Maybe we should follow to proposal in #61005 and preserve entered by programmer expression (math.e or 0o666 or 2**63-1)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directory

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions