2

I am very curious about the classes that exist in the module builtins that are not accessible directly. Such as

 type(lambda: 0) # __name__='function' of __module__='builtins'
 type((lambda: 0).__code__) # __name__='code' (aka. bytecode) of __module__='builtins'
 None.__class__  # __name__='NoneType' of __module__='builtins'

And the matriarch:

str.__mro__[1] #  # __name__='object' of `__module__` 'builtins'

traceback as passed to the __exit__ magic method of a context manager is the same:

 def __exit__(self, exc_type: Exception, exc_value: str, exc_traceback: 'bultins.traceback'):
      pass

(The module traceback is a module and simply shares the name, ditto for tracemalloc.Traceback). In the above the object name is a string, but this is a rare example of a "hidden" builtins class and typehinting because for a function instances typing.Callable does the job.

Q: what is the name for these "hidden" builtin classes?

I understand that the builtins are written in C in CPython. I had a quick gander at the CPython Github repo and I could not figure out why unlike tuple they are "hidden". I use the word "classes" as they have the same magic methods etc. and work like other classes:

 NoneType() == None  # True as expected
 bytecode = code(...)  #  bytecode...
 fxn = function(bytecode)

Q: Is there a PEP reason why they are not in builtins?

If it is simply to stop namespace pollution, I'd have though they'd be underscored objects in the builtin module say or in some module... unless they are somewhere else

Q: Can they be imported directly by somewhere else?!

Matteo Ferla
  • 2,128
  • 1
  • 16
  • 27
  • I ask simply to understand what they are may help me in the future. This phylosophical question was prompted by typehinting traceback, which the ugly `exc_traceback: 'bultins.traceback'` does. So I don't have a specific problem in mind... – Matteo Ferla Feb 04 '21 at 13:53
  • A few days back I came across a lovely example where these "hidden" built-ins were sought: https://stackoverflow.com/questions/8294618/define-a-lambda-expression-that-raises-an-exception – Matteo Ferla Feb 04 '21 at 13:55

1 Answers1

1

Maybe as an answer to reasoning – afaik, this is about not providing public API that goes agains semantics.

I.e. instantiating NoneType is something that you rather should not do, same as doing equality comparison for None.

If you have specific needs to build something dynamically – please provide them, usually there's an official API to do so (ast, as an example)

Slam
  • 8,112
  • 1
  • 36
  • 44
  • That is a good point about `ast` and not screwing up the semantics. NoneType is the easiest to use, but even if NoneType works fine and one could envisage a function that passed a class instantiates it, having NoneType and None kicking around would be dangerous in all other cases. (Oh, and yes, I normally use the `is` keyword, I use equality in the example as I wanted to test that it still worked fully by showing they were equal and the same —the hash of `None` and `None.__class__()` are the same high digit number) – Matteo Ferla Feb 04 '21 at 15:03