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/