On 1/12/21 8:23 PM, Neil Schemenauer wrote:
On 2021-01-12, Pablo Galindo Salgado wrote:
One worry that I have in general with this move is the usage of
_PyType_GetModuleByDef to get the type object from the module
definition. This normally involves getting a TLS in every instance
creation, which can impact notably performance for some
perf-sensitive types or types that are created a lot.

I would say _PyType_GetModuleByDef is the problem.  Why do we need
to use such an ugly approach (walking the MRO) when Python defined
classes don't have the same performance issue?  E.g.

     class A:
         def b():
             pass
     A.b.__globals__

IMHO, we should be working to make types and functions defined in
extensions more like the pure Python versions.

Related, my "__namespace__" idea[1] might be helpful in reducing the
differences between pure Python modules and extension modules.
Rather than functions having a __globals__ property, which is a
dict, they would have a __namespace__, which is a module object.
Basically, functions and methods known which global namespace
(module) they have been defined in.  For extension modules, when you
call a function or method defined in the extension, it could be
passed the module instance, by using the __namespace__ property.

Maybe I'm missing some details on why this approach wouldn't work.
However, at a high level, I don't see why it shouldn't.  Maybe
performance would be an issue?  Reducing the number of branches in
code paths like CALL_FUNCTION should help.

The main difference between Python and C functions is that in C, you need type safety. You can't store C state in a mutable dict (or module) accessible from Python, because when users invalidate your C invariants, you get a segfault rather than a nice AttributeError.

Making methods "remember" their context does work though, and has already been implemented -- see PEP 573! It uses the *defining class* instead of __namespace__, but you can get the module from that quite easily.

The only place it doesn't work are slot methods, which have a fixed C API. For example:

    PyObject *tp_repr(PyObject *self);
    int tp_init(PyObject *self, PyObject *args, PyObject *kwds);

There is no good way to pass the method, module object, globals() or the defining class to such functions.


1. https://github.com/nascheme/cpython/tree/frame_no_builtins
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/TZVSCCCTUISV32U2OTE5LY7F3X5QAVCX/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to