Steven, you're making a pretty good case here, but a couple questions:

1) The case of newer versions of python adding methods to builtins, like .bit_length is really compelling. But I do wonder how frequently that comes up. It seems to me on this list, that people are very reluctant to add methods to anything builtin (other than dunders) -- particularly ABCs, or classes that might be subclassed, as that might break anything that currently uses that same name. Anyway, is this a one-off? or something that is likely to come up semi-frequently in the future?

Note also that the py2 to py3 transition was (Hopefully) an anomaly -- more subtle changes between versions make it less compelling to support old versions for very long.

2) Someone asked a question about the term "Extension Methods" --  I assume it's "Extension attributes", where the new attribute could be anything, yes?

2) Comprehensibility:

Seriously, there's a time to realise when arguments against a feature
devolve down to utterly spurious claims that Python programmers are
idiots who will be confused by:

    from extensions use flatten
    mylist.flatten()

but can instantly understand:

    from extensions import flatten
    flatten(mylist)

No -- we're not assuming Python users are idiots -- there is an important difference here:

    from extensions import flatten
    flatten(mylist)

very clearly adds the name `flatten` to the current module namespace. That itself can be confusing to total newbies, but yes, you can't get anywhere with Python without knowing that. Granted, you still need need to know what `flatten` is, and what it does some other way in any case. Whereas:

    from extensions use flatten
    mylist.flatten()

does NOT import the name `flatten` into the local namespace -- which I suppose will be "clear" because it's using "use" rather than a regular import, but that might be subtle. But importantly, what it has done is add a name to some particular type -- what type? who knows?

In this example, you used the name "mylist", so I can assume it's an extension to list. But if that variable were called "stuff", I"d have absolutely no idea. And as above, you'd need to go find the documentation for the flatten extension method, just as you would for any name in a module, but somehow functions feel more obvious to me.

Thinking about this I've found what I think is a key issue for why this may be far less useful for Python that it is for other languages. Using teh "flatten" example, which I imagine you did due to the recent discussion on this list about the such a function as a potential new builtin:

Python is dynamically Polymorphic (I may have just made that term up -- I guess it's the same as duck typed) -- but what that means in that context is that I don't usually care exactly what type an object is -- only that it supports particular functionality, so, for instance:

from my_utilities import flatten

def func_that_works_with_nested_objects(the_things):
    all_the_things_in_one  = flatten(the_things)
    ...

Presumably, that could work with any iterable with iterables in it.

but

from my_extensions use flatten

def func_that_works_with_nested_objects(the_things):
    all_the_things_in_one  = the_things.flatten

OOPS! that's only going to work with actual lists.

Are you thinking that you could extend an ABC? Or if not that, then at least a superclass and get all subclasses? I'm a bit confused about how the MRO might work there.

Anyway, in my mind THAT is the big difference between Python and at least mony  of the languages that support extension methods.

A "solution" would be to do what we do with numpy -- it has an "asarray()" function that is a no-op if the argument is a numpy array, and creates an array if it's not. WE often put that at the top of a function, so that we can then use all the nifty array stuff inside the function, but not requires the caller to create an array firat. But that buys ALL the numpy functionality, it would be serious overkill for a method or two.

It's not a reason it couldn't work, or be useful, but certainly a lot less useful than it might be.

In fact, the example for int.bit_length may b e the only compelling use case -- not that method per se, but a built-in type that is rarely duck-typed. That would be integers, floats and strings, at least those are the most common. even ints and floats are two types that are frequently used  interchangeably.

Side note:

I don't see the relevance to extension methods. You seem to be just
listing random facts as if they were objections to the extension method
proposal.

Let's keep this civil, and assume good intentions -- if something is irrelevant, it's irrelevant, but please don't assume that the argument was not made in good faith. For my part I've been following this thread, but only recently understood the scope of the proposal well enough to know that e.g. the above issue was not relevant.

-Chris B

--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython