[Python-Dev] PEP 575 (Unifying function/method classes) update

Jeroen Demeyer J.Demeyer at UGent.be
Tue May 15 05:15:27 EDT 2018


On 2018-05-14 19:56, Petr Viktorin wrote:
> It does quite a lot of things, and the changes are all intertwined,
> which will make it hard to get reviewed and accepted.

The problem is that many things *are* already intertwined currently. You 
cannot deal with functions without involving methods for example.

An important note is that it was never my goal to create a minimal PEP. 
I did not aim for changing as little as possible. I was thinking: we are 
changing functions, what would be the best way to implement them?

The main goal was fixing introspection but a secondary goal was fixing 
many of the existing warts with functions. Probably this secondary goal 
will in the end be more important for the general Python community.

I would argue that my PEP may look complicated, but I'm sure that the 
end result will be a simpler implementation than we have today. Instead 
of having four related classes implementing similar functionality 
(builtin_function_or_method, method, method_descriptor and function), we 
have just one (base_function). The existing classes like method still 
exist with my PEP but a lot of the core functionality is implemented in 
the common base_function.

This is really one of the key points: while my PEP *could* be 
implemented without the base_function class, the resulting code would be 
far more complicated.

> Are there parts that can be left to a subsequent PEP, to simplify the
> document (and implementation)?

It depends. The current PEP is more or less a finished product. You can 
of course pick parts of the PEP and implement those, but then those 
parts will be somewhat meaningless individually.

But if PEP 575 is accepted "in principle" (you accept the new class 
hierarchy for functions), then the details could be spread over several 
PEPs. But those individual PEPs would only make sense in the light of 
PEP 575.

A few small details could be left out, such as METH_BINDING. But that 
wouldn't yield a significant simplification.

> It seems to me that the current complexity is (partly) due to the fact
> that how functions are *called* is tied to how they are *introspected*.

The *existing* situation is that introspection is totally tied to how 
functions are called. So I would argue that my PEP improves on that by 
removing some of those ties by moving __call__ to a common base class.

> Maybe we can change `inspect` to use duck-typing instead of isinstance?

That was rejected on https://bugs.python.org/issue30071

> Then, if built-in functions were subclassable, Cython functions could
> need to provide appropriate __code__/__defaults__/__kwdefaults__
> attributes that inspect would pick up.

Of course, that's possible. I don't think that it would be a *better* 
solution than my PEP though.

Essentially, my PEP started from that idea. But then you realize that 
you'll need to handle not only built-in functions but also method 
descriptors (unbound methods of extension types). And you'll want to 
allow __get__ for the new subclasses. For efficiency, you really want to 
implement __get__ in the base classes (both builtin_function_or_method 
and method_descriptor) because of optimizations combining __get__ and 
__call__ (the LOAD_METHOD and CALL_METHOD opcodes). And then you realize 
that it makes no sense to duplicate all that functionality in both 
classes. So you add a new base class. You already end up with a major 
part of my PEP this way.

That still leaves the issue of what inspect.isfunction() should do. 
Often, "isfunction" is used to check for "has introspection" so you 
certainly want to allow for custom built-in function classes to satisfy 
inspect.isfunction(). So you need to involve Python functions too in the 
class hierarchy. And that's more or less my PEP.


Jeroen.


More information about the Python-Dev mailing list