[Python-ideas] Re: Flatten function (was: Deprecate sum of lists)

2021-06-20 Thread Oscar Benjamin
On Sun, 20 Jun 2021 at 23:29, Greg Ewing  wrote:
>
> On 21/06/21 6:04 am, Sebastian Berg wrote:
> > * `flatten()` (alwasy copy)
> > * `ravel()` (copies if needed, and additionally ensures contiguity)
> > * `reshape(-1)` (copies if needed)
> >
> > They are all subtly different, unfortunately.
>
> There's also a .flat attribute, that returns a 1-d iterator!

There's also np.concatenate which to me seems like the closest to what
sum does with lists.

If there is a problem to solve here it's that people want to
concatenate things and reach out to the sum function because the
concatenate function doesn't exist. The sum function refuses to sum
strings but the preferred alternative is
text = ''.join(strings)
which is just weird looking. Why would you call a method on the empty
string? It would be much better spelt as
text = concatenate(strings)
and that spelling could work equally well for lists, tuples, etc.

-- 
Oscar
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YFGGY4TDNHHEGJ2T5UED67W44SXRKNHA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread William Pickard
Your assumption about requiring some form of registration system for Python to 
implement extensions is correct as Roslyn (The C# compiler) resolves them at 
compile time (as long as the namespace is imported/the class is in the "global" 
namespace)

When I said static function, it's basically me saying static method, and 
they're the same as a method in python with "@staticmethod" applied to it.

here's a sample "prototype" of a System.Linq extension method (a very useful 
one imo):

"namespace System.Linq
{
public static class Enumerable
{
public static IEnumerable Select(this 
IEnumerable enumerable, Func selector);
}
}"

As you can see, the param "enumerable" is prefixed by the "this" keyword, this 
tells Roslyn to treat "enumerable" as if it was the special implicit "this" 
operator in instance methods:

"using System.Linq;

namespace MyNS
{
public sealed class MyCLS
{
public static readonly List MyInts = new List() { 0, 5, 12, 
56, 9 };

public int RNG = 42;

public IEnumerable ExpandInts()
{
return MyInts.Select(@int => @int * this.RNG);
}
}
}"

As you can see in the above to quoted blocks (SOMEONE TELL ME HOW TO DO CODE 
BLOCKS!), I'm using the extension method "Select" defined in "Enumerable" as if 
it was defined on the interface "IEnumerable" when it's actually not. 
(List implements IList which inherits ICollection which inherits 
IEnumerable)

The only requirement is that both the static class AND the method is visible to 
your code (with public being visible to everyone)

Here's the official docs: 
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/UMINJUP4PG5WXY3W2MUYJL2DQ4GTVOWH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread Steven D'Aprano
Hi William,

Thanks for the description of C# extension methods, but I think that 
like Britons and Americans, we're in danger of being divided by a common 
language. (To paraphrase Churchill.)

On Sun, Jun 20, 2021 at 10:56:37PM -, William Pickard wrote:

> While IDK about Kotlin's extension methods, I do know that C# (A 
> highly popular programming language) also has extension methods so 
> I'll talk about those.
> 
> In C#, extension methods are plain static functions defined in a plain 
> static class, the only key difference between normal static methods 
> and these extension methods is that the first argument is prefixed 
> with the "this" keyword.

I'm unsure what you mean by "static functions" and whether they are the 
same thing as "static methods". I believe that a static method is 
something different in Python and C#.

When you say *prefixed by*, surely you don't actually mean a literal 
prefix? Using Python syntax:

# I want the first argument to be called "param".
def extension(thisparam):

because that would be silly *wink* so I guess that you mean this:

def extension(this, param):

except that in Python, we spell it "self" rather than "this", and it is 
not a keyword. So as far as the interpreter is concerned, whether 
spelled as "this", "self" or something else, that's just a regular 
function that takes two parameters, neither of which has any special or 
pre-defined meaning.


> You can invoke extension methods as if they were defined on the type 
> they're extending without actually changing the type, the only 
> requirement is that the namespace that the class containing the method 
> is used (via "using").

Let me see if I can interpret that, in Python terms.

Suppose we have a module X.py which defines a list extension method 
imaginatively called "extension". In order to use that method from my 
module, I would have to say:

using X

first, after which:

hasattr(list, 'extension')

would return True. Otherwise, it would continue to return False. So 
modules have to opt-in to use the extension method, rather than having 
the methods foist on them as in monkey-patching.

Am I close?

I think this sounds much more promising, since it avoids the downsides 
of monkey-patching. The problem is that in a language like C#, and I 
presume Koitlin, methods are resolved at compile time, but in Python 
they are resolved at runtime.

So `using` would have to be some sort of registration system, which 
would require every attribute lookup to go through the registration 
system looking for only those extension methods which are being used by 
the current module.

I expect that would be slow and complex. But maybe I'm just not clever 
enough to think of an efficient way of handling it :-(


-- 
Steve
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3WSJPQGYRETFNVKNMIAPQ7DB52JD4ZDQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread Soni L.



On 2021-06-20 7:48 p.m., Steven D'Aprano wrote:
> The technique you are calling "extension methods" is known as 
> "monkey-patching" in Python and Ruby.
>
> With respect to a fine language, Kotlin, it doesn't have the user-base 
> of either Python or Ruby. Python does not allow monkey-patching builtin 
> classes, but Ruby does:
>
> https://avdi.codes/why-monkeypatching-is-destroying-ruby/
>
> A cautionary tale. So what does Kotlin do to prevent that sort of thing?
>
> Can you use a regular function that takes a list as argument, instead of 
> monkey-patching the list class to add a method?
>
> The beauty of a function is that every module is independent, so they 
> can add their own list extensions (as functions) without stomping over 
> each other. Whereas if they add them directly on to the list class 
> itself, they can clash.
>

The trick to extension methods is that they're only available when you
explicitly use them.

In other words, a module/package can't force them on you.

The problem with "monkey-patching" is that it *does* get forced on you.

With the way Python works, your only option to implement extension
methods is to monkey-patch __getattr__. An alternative would be to have
a module-level __getattr__, which by default resolves to the object's
own attributes, but can be replaced by the module to provide proper
(module-local) extension methods functionality. Thus, any module-local
extension methods would also take priority over subclasses' attributes,
without conflicting with them.

(It would also slow everything down af, but that's beside the point.)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/Q4WLJWTTY3AEK7SRVJ3TAFRHQOP6CKG3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread William Pickard
While IDK about Kotlin's extension methods, I do know that C# (A highly popular 
programming language) also has extension methods so I'll talk about those.

In C#, extension methods are plain static functions defined in a plain static 
class, the only key difference between normal static methods and these 
extension methods is that the first argument is prefixed with the "this" 
keyword.

You can invoke extension methods as if they were defined on the type they're 
extending without actually changing the type, the only requirement is that the 
namespace that the class containing the method is used (via "using"). Infact, 
.NET ships with a bunch of extension methods just for the IEnumerable and 
IEnumerable interfaces in System.LINQ.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PFNZ7RLRKQEVKPI3WHRLOKFDCYFZOZZS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread Steven D'Aprano
The technique you are calling "extension methods" is known as 
"monkey-patching" in Python and Ruby.

With respect to a fine language, Kotlin, it doesn't have the user-base 
of either Python or Ruby. Python does not allow monkey-patching builtin 
classes, but Ruby does:

https://avdi.codes/why-monkeypatching-is-destroying-ruby/

A cautionary tale. So what does Kotlin do to prevent that sort of thing?

Can you use a regular function that takes a list as argument, instead of 
monkey-patching the list class to add a method?

The beauty of a function is that every module is independent, so they 
can add their own list extensions (as functions) without stomping over 
each other. Whereas if they add them directly on to the list class 
itself, they can clash.

As for code readability, I don't think that this:

mylist.first_or_none()

is particularly more readable than:

first_or_none(mylist)


Not everything has to be wrapped in a class.

https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html


-- 
Steve
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/2RI34EPKL2MLZTOFB2XM6KCAUXW3CDSD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Flatten function (was: Deprecate sum of lists)

2021-06-20 Thread Greg Ewing

On 21/06/21 6:04 am, Sebastian Berg wrote:

* `flatten()` (alwasy copy)
* `ravel()` (copies if needed, and additionally ensures contiguity)
* `reshape(-1)` (copies if needed)

They are all subtly different, unfortunately.


There's also a .flat attribute, that returns a 1-d iterator!

--
Greg
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/K6MEDWIRNXK6ES5RKM22SESPZFNBHFWZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Fill in missing contextvars/asyncio task support

2021-06-20 Thread Mark Gordon
With normal synchronous code you can use `contextvars.Context.run()` to change 
what context code is executing within. However, there is no analagous concept 
for asyncio code. I'm proposing something similar, for example:

coro = foo()
my_context = convextvars.Context()
await asyncio.run_in_context(coro)

Currently the workaround is to run the coroutine on a separate task.

coro = foo()
my_context = convextvars.Context()
await my_context.run(asycnio.create_task, coro)

However this is not exactlly the same as the task will inherit a copy of 
my_context rather than running directly on my_context. Additionally (obviously) 
it will also be running in a separate task.

Similarly it would be nice if create_task and the Task constructor could take 
an optional context kwarg to use as the task context rather than the default of 
copying the calling context.

Pull request with sample implementation (although I think missing the change to 
create_task): https://github.com/python/cpython/pull/26664
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3EQO67J7IBAO6YSK2LBIPU4E7HU6UQJH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Flatten function (was: Deprecate sum of lists)

2021-06-20 Thread David Mertz
On Sun, Jun 20, 2021, 2:07 PM Sebastian Berg

> NumPy has:
>
> * `flatten()` (always copy)
> * `ravel()` (copies if needed, and additionally ensures contiguity)
> * `reshape(-1)` (copies if needed)
>
> They are all subtly different, unfortunately.
>

Oops! Sebastian is right, and I made an error. NumPy ndarray.flatten() is
indeed a copy. ndarray.ravel() is usually a view.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FNVCLMSUY47Y7SGBIPIERLIZQCNFO7KU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Flatten function (was: Deprecate sum of lists)

2021-06-20 Thread Sebastian Berg
On Sun, 2021-06-20 at 13:48 -0400, David Mertz wrote:
> On Sun, Jun 20, 2021 at 1:07 PM Christopher Barker <
> python...@gmail.com>
> wrote:
> 
> > Flatten is used in numpy:
> > Where it is a method, and goes all the way to one dimension.
> > 
> 
> I think it's worth keeping in mind the differences though.  In NumPy,
> arr.flatten() doesn't even TOUCH the array itself.  It is solely a
> manipulation of the `.shape` attribute.  In essence, we could define
> it
> like this:

Passer by comment.  But that is not true: `flatten` explicitly copies
the data and does not create a view (in case the argument was about
names).

NumPy has:

* `flatten()` (alwasy copy)
* `ravel()` (copies if needed, and additionally ensures contiguity)
* `reshape(-1)` (copies if needed)

They are all subtly different, unfortunately.

- Sebastian


> 
> arr.flatten = lambda a: a.reshape(reduce(mul, a.shape, 1))
> 
> Actual NumPy arrays don't allow attaching a monkey-patch method, but
> if
> they did that would be it.  I guess this example relies on knowing
> that
> `.reshape` also doesn't touch the data though (in particular, zero
> memory
> copies).
> 
> A builtin flatten can’t be the same, but it would be nice if it
> weren’t too
> > different. e.g. list(flatten(a_2d_array)) would do the same thing
> > as
> > list(a_2d_array.flatten()).
> > For a builtin, perhaps it could take an optional integer “depth”
> > parameter
> > which would provide flexibility and be one way to control its
> > behavior with
> > strings.
> > 
> 
> I think that would be nice as a signature.  I don't really care about
> builtin vs itertools, but something like `flatten(seq, depth=2)`
> would be
> handy.  The question is really whether the default depth is 1 or
> sys.maxsize.  Both have plausible cases.  Some special depth like 2
> or 3
> could be useful at times, but definitely should not be default.
> 
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/UAJVPXSXR3JNBTEOPEPTWHAZIQUM637N/
> Code of Conduct: http://python.org/psf/codeofconduct/


___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DSQ6USYIRET5IP66NG6UGFVXBC2MKRWU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Flatten function (was: Deprecate sum of lists)

2021-06-20 Thread David Mertz
On Sun, Jun 20, 2021 at 1:07 PM Christopher Barker 
wrote:

> Flatten is used in numpy:
> Where it is a method, and goes all the way to one dimension.
>

I think it's worth keeping in mind the differences though.  In NumPy,
arr.flatten() doesn't even TOUCH the array itself.  It is solely a
manipulation of the `.shape` attribute.  In essence, we could define it
like this:

arr.flatten = lambda a: a.reshape(reduce(mul, a.shape, 1))

Actual NumPy arrays don't allow attaching a monkey-patch method, but if
they did that would be it.  I guess this example relies on knowing that
`.reshape` also doesn't touch the data though (in particular, zero memory
copies).

A builtin flatten can’t be the same, but it would be nice if it weren’t too
> different. e.g. list(flatten(a_2d_array)) would do the same thing as
> list(a_2d_array.flatten()).
> For a builtin, perhaps it could take an optional integer “depth” parameter
> which would provide flexibility and be one way to control its behavior with
> strings.
>

I think that would be nice as a signature.  I don't really care about
builtin vs itertools, but something like `flatten(seq, depth=2)` would be
handy.  The question is really whether the default depth is 1 or
sys.maxsize.  Both have plausible cases.  Some special depth like 2 or 3
could be useful at times, but definitely should not be default.

-- 
The dead increasingly dominate and strangle both the living and the
not-yet born.  Vampiric capital and undead corporate persons abuse
the lives and control the thoughts of homo faber. Ideas, once born,
become abortifacients against new conceptions.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/UAJVPXSXR3JNBTEOPEPTWHAZIQUM637N/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Deprecate sum of lists

2021-06-20 Thread Christopher Barker
Flatten is used in numpy:

https://numpy.org/doc/stable/reference/generated/numpy.ndarray.flatten.html?highlight=flatten#numpy.ndarray.flatten

Where it is a method, and goes all the way to one dimension.

A builtin flatten can’t be the same, but it would be nice if it weren’t too
different. e.g. list(flatten(a_2d_array)) would do the same thing as
list(a_2d_array.flatten()).

For a builtin, perhaps it could take an optional integer “depth” parameter
which would provide flexibility and be
one way to control its behavior with strings.

-CHB

On Sat, Jun 19, 2021 at 8:36 AM Marc-Andre Lemburg  wrote:

> On 19.06.2021 17:17, Serhiy Storchaka wrote:
> > 19.06.21 18:12, Marc-Andre Lemburg пише:
> >>> But there could be endless debate about whether flatten( ("x", "y") )
> should
> >>> return a list or a tuple...
> >>
> >> Have it return an iterator :-)
> >
> > flatten = itertools.chain.from_iterable
>
> Well, like I said: modulo the discussion around what "flatten"
> should mean, e.g. you will probably want to have flatten() go
> a certain number of levels deep and not necessarily flatten
> strings.
>
> But yes, such a definition is certainly a good start.
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Jun 19 2021)
> >>> Python Projects, Coaching and Support ...https://www.egenix.com/
> >>> Python Product Development ...https://consulting.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>https://www.egenix.com/company/contact/
>  https://www.malemburg.com/
>
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/5C2JB3QU7E4S5MMRI7NCRSZ52MFKZCC5/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JVEEG6HN73Z3DDYZMWYTFQ7TRF3FLAN3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread 2QdxY4RzWzUUiLuE
On 2021-06-20 at 12:18:24 -,
Johan Vergeer  wrote:

> After working with Kotlin for a while I really started to like the
> idea of extension methods. I delivers a great way to extend the
> language without having to add features to the language itself.

I disagree with the premise that such a thing is great, although it does
have limited use cases (mostly revolving around bugs, whether you know
about the bug or are tracking it down).

That said, Python already allows it:

>>> class C: pass
>>> c = C()
>>> C.f = lambda self, *a: a # add method f to class C
>>> c.f(5, 6)
(5, 6)

See also .
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/AFPRRXLWK2ZHXVUTRRJ57KI6HF6LWZH6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Extension methods in Python

2021-06-20 Thread Rob Cliffe via Python-ideas

What objection do you have to creating a subclass?
Adding methods to e.g. list could give you problems if you import 2 
modules that each modify list and the modifications are incompatible.  
It could conceivably add bugs to code that uses list in a standard way.

Best wishes
Rob Cliffe

On 20/06/2021 13:18, Johan Vergeer wrote:

After working with Kotlin for a while I really started to like the idea of 
extension methods. I delivers a great way to extend the language without having 
to add features to the language itself.

As a practical example I would like to take a first item from a list

my_list = []
first = my_list[0] # This will obviously throw an error

In this case it would be great to create an extension method like

def list.first_or_none(self):
 if len(self):
 return self[0]
 return None

Or ...

def list.first_or_else(self, fallback_value):
 if len(self):
 return self[0]
 return fallback_value

Then, we could retrieve a value from the list:

from my_list_extensions import first_or_none, first_or_else

first = my_list.first_or_none()
Or ...
first = my_list.first_or_else(0)

Some of the main advantages (not an exhaustive list):
- It also provides a way to add extension methods before adding methods to the 
standard library, like in PEP 616
- Classes can be extended without using inheritance
- Easier for IDE's to know what methods are available for a type, therefore 
delivering auto-completion.
- It would also become easier to extend classes from other libraries next to 
the standard library
- It will be much easier to create methods on a class that can be chained, 
which leads to less intermediate variables and (in my opinion) better 
readability. Sometimes these are called fluent builders or fluent interfaces.

my_list.filter(lambda x: x >= 0).map(lambda x: str(x)) instead of [str(x) for x in 
my_list if x >= 0]. (ok, in hindsight this looks better with the list 
comprehension, but there are much more complicated examples that would benefit)

A more comprehensive example would be an html builder. Let's say I created a 
library that builds html from python code, with a nice builder interface:

class Html:
 def __init__(self):
 self.__items = []

 def add_p(self, text):
 self.__items.append(text)
 return self

 def add_h1(self, text):
 self.__items.append(text)
 return self

 def add_div(self, items):
 self.__items.append(items)
 return self

To add methods (which is very likely in a class like this), I would have to 
create a subclass, or create a pull request with the author (if the author 
approves).

In all languages that I know of that have extension methods the most given 
argument is better code readability.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/QXS73E5ZSV7ZJH4XWR2OOUGUA4UCFBS6/
Code of Conduct: http://python.org/psf/codeofconduct/


___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/4URIELNC5NHZUBHFBQOZWDSDI5WYVGKR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Extension methods in Python

2021-06-20 Thread Johan Vergeer
After working with Kotlin for a while I really started to like the idea of 
extension methods. I delivers a great way to extend the language without having 
to add features to the language itself. 

As a practical example I would like to take a first item from a list

my_list = []
first = my_list[0] # This will obviously throw an error

In this case it would be great to create an extension method like

def list.first_or_none(self):
if len(self):
return self[0]
return None

Or ...

def list.first_or_else(self, fallback_value):
if len(self):
return self[0]
return fallback_value

Then, we could retrieve a value from the list:

from my_list_extensions import first_or_none, first_or_else

first = my_list.first_or_none()
Or ...
first = my_list.first_or_else(0)

Some of the main advantages (not an exhaustive list):
- It also provides a way to add extension methods before adding methods to the 
standard library, like in PEP 616
- Classes can be extended without using inheritance
- Easier for IDE's to know what methods are available for a type, therefore 
delivering auto-completion.
- It would also become easier to extend classes from other libraries next to 
the standard library
- It will be much easier to create methods on a class that can be chained, 
which leads to less intermediate variables and (in my opinion) better 
readability. Sometimes these are called fluent builders or fluent interfaces.

my_list.filter(lambda x: x >= 0).map(lambda x: str(x)) instead of [str(x) for x 
in my_list if x >= 0]. (ok, in hindsight this looks better with the list 
comprehension, but there are much more complicated examples that would benefit)

A more comprehensive example would be an html builder. Let's say I created a 
library that builds html from python code, with a nice builder interface:

class Html:
def __init__(self):
self.__items = []

def add_p(self, text):
self.__items.append(text)
return self

def add_h1(self, text):
self.__items.append(text)
return self

def add_div(self, items):
self.__items.append(items)
return self

To add methods (which is very likely in a class like this), I would have to 
create a subclass, or create a pull request with the author (if the author 
approves). 

In all languages that I know of that have extension methods the most given 
argument is better code readability.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/QXS73E5ZSV7ZJH4XWR2OOUGUA4UCFBS6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Allow modifying message of TypeError from NotImplemented

2021-06-20 Thread Serhiy Storchaka
19.06.21 06:30, wyz2...@163.com пише:
> Python raises TypeError when NotImplemented is returned from __add__, 
> __invert__ etc. and __radd__ etc. aren't available.
> However, this disallows the customization of error messages. For example, in 
> Python 3.8, __float__ etc. were removed from complex to allow methods like 
> __rfloat__. But this makes abs(z) undiscoverable for many users. The original 
> error message is very helpful.
> I suggest to make a way for this usage. Maybe NotImplementedType can accept 
> *args, and NotImplemented can be callable, equal to __init__:
> 
 class A:
> def __add__(self, other):
> return NotImplemented  # Just like before
> def __neg__(self, other):
> return NotImplemented(f'bad operand type for unary -: 
> {type(self).__name__!r}; use ~ to invert')  # <--
> def __invert__(self):
> return ~5
 a = A()
 a + 2
> TypeError: unsupported operand type(s) for +: 'A' and 'int'
 -a
> TypeError: bad operand type for unary -: 'A'; use ~ to invert
 ~a
> -6

NotImplemented is a singleton. And all code which tests for
NotImplemented does it by checking identity. Returning any other object
instead of the NotImplemented would not work.

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/R6P566R4YQBRRB3KMEROK7FGSRIWJXCO/
Code of Conduct: http://python.org/psf/codeofconduct/