[Python-ideas] Re: Auto-assign attributes from __init__ arguments

2020-05-07 Thread Lewis Ball
> Although I might use it a lot (more than I would like to admit), I don't
> like this feature. First of all, I think it favors not-very-pretty code,
> effectively reducing the cost you pay for writing too-many-argument
> functions. It'd also obfuscate the code, and here I would like to quote the
> Zen of Python "explicit is better than implicit".
Yeah I get what you are saying, although in my opinion having to write each 
argument name 3 times in the __init__ makes code harder to read and obfuscated 
the code more than this would. Also, there are times when too-many-argument 
functions are necessary, and several examples of these can be found in the 
stdlib.

> I think he idea of positional only args is that you don't want whoever
> is calling you to care about
> the variable names they will have inside your code whatsoever.

I was thinking that excluding them might be more confusing though, and even not 
explicitly named when passed, they are probably set to an arribute with the 
same name as the arg like most other args. Either way, these minor details can 
be worried about if this becomes popular.

I can't see this being used if it is implemented outside of stdlib, because the 
warning from linter would drive people mad. I suppose it needs to either be 
added to stdlib or forgotten about.
___
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/3LEYVR6EL52EHUVIPULHBIKLKWBYDX3E/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 618: Add Optional Length-Checking To zip

2020-05-07 Thread David Mertz
On Thu, May 7, 2020 at 4:42 AM Kirill Balunov 
wrote:

> `chain(*iterable)` converts iterable into a tuple, concretizing it in
>> memory. chain.from_iterable(iterable) is lazy and goes through the elements
>> one a time, meaning iterable can be infinite.
>>
>
> "meaning iterable can be infinite"  -  thank you, I missed this part, but
> to be honest I don’t remember when I do something useful with
> infinite iterables.
>

Being fuzzy about "infinite" versus "very large" here are a couple examples:

>>> def first_ints():
... from random import randint
... while True:
... yield range(randint(10, 20))
...
>>> from itertools import chain
>>> nums = chain.from_iterable(first_ints())
>>> from itertools import islice
>>> list(islice(nums, 100, 150))
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
1, 2, 3, 4, 5, 6]

In this code we want initial sequences of non-negative integers of varying
lengths, repeated... because MATH.  I could not concretize the infinite
collection of finite sequences.

Here's an example that is just "very big" instead of infinite, but would
still urge for .from_iterable().

>>> def all_man_lines(path='/usr/share/man/man1/'):
... from glob import glob
... for fname in glob(f"{path}*.gz"):
... yield gzip.open(fname)
...
>>> lines = chain.from_iterable(all_man_lines())
>>> for line in islice(lines, 100, 105):
... print(line)
...
b".ds ^ k:\\h'-(n(.wu*10/11-\\*(#H)'^\\h'|n:u'\n"
b".ds , k:\\h'-(n(.wu*8/10)',\\h'|n:u'\n"
b".ds ~ k:\\h'-(n(.wu-\\*(#H-.1m)'~\\h'|n:u'\n"
b".ds / k:\\h'-(n(.wu*8/10-\\*(#H)'\\z\\(sl\\h'|n:u'\n"
b'.\\}\n'

I do not have infinitely many man pages on my system, but I have enough of
them that I don't want to open file handles to all of them at once.

-- 
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/YS4EZBUNCO6SJOYHPPBKA3ESHGFA7FAY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Rhodri James

On 07/05/2020 10:11, Steven D'Aprano wrote:

On Sat, May 02, 2020 at 05:12:58AM -, Ahmed Amr wrote:


Currently, when comparing a list of items to an array of the same
items for equality (==) it returns False, I'm thinking that it would
make sense to return True in that context, as we're comparing item
values and we have the same way of indexing both collections, so we
can compare item values.


I'm going to throw out a wild idea (actually not that wild :-) that I'm
sure people will hate for reasons I shall mention afterwards.

Perhaps we ought to add a second "equals" operator?


The biggest argument against a second "equals" operator, however it is 
spelt, is confusion.  Which of these two operators do I want to use for 
this subtly different question of equality?  Even where we have quite 
distinct concepts like "==" and "is", people still get muddled.  If we 
have "==" and "=OMG=" or whatever, that would just be an accident 
waiting to happen.


Cheers,
Rhodri

--
Rhodri James *-* Kynesim Ltd
___
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/A2WS4OAVFIROJ5T5WPVCS2XK2IZEWEVU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Dan Sommers
On Thu, 7 May 2020 21:18:16 +1000
Steven D'Aprano  wrote:

> > The strongest equality is the "is" operator
> 
> Please don't encourage the conceptual error of thinking of `is` as 
> *equality*, not even a kind of equality. It doesn't check for equality, 
> it checks for *identity* and we know that there is at least one object 
> in Python where identical objects aren't equal:
> 
> py> from math import nan
> py> nan is nan
> True
> py> nan == nan
> False

We'd better agree to disagree on this one.

> > The very far ends of that scale are glossing over American
> > vs. British spellings (are "color" and "colour" in some sense equal?),
> 
> YAGNI.

> The proposal here is quite simple and straightforward, there is no
> need to over-generalise it to the infinite variety of possible
> equivalencies than someone might want. People can write their own
> functions.

YAGNI is how I feel about an operator that compares sequences element by
element.  People can write their own functions.  :-)  Or add your .EQ.
function to the standard library (or even to builtins, and no, I don't
have a good name).

> It is only that wanting to compare two ordered containers for equality
> of their items without regard to the type of container is a reasonably
> common and useful thing to do.

> Even if we don't want list==tuple to return True -- and I don't! -- we
> surely can recognise that sometimes we don't care about the
> container's type, only it's elements.

Do "reasonably common," "useful," and "sometimes" meet the bar for a new
operator?  (That's an honest question and not a sharp stick.)

FWIW, I agree:  list != tuple.  When's the last time anyone asked for
the next element of a tuple?  (Okay, if your N-tuple represents a point
in N-space, then you might iterate over the coordinates in order to
discover a bounding box.)

Dan

-- 
“Atoms are not things.” – Werner Heisenberg
Dan Sommers, http://www.tombstonezero.net/dan
___
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/N5OMIARPTO2GATG7ANLVUJ7HZHGKP5NY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto-assign attributes from __init__ arguments

2020-05-07 Thread Joao S. O. Bueno
On Wed, 6 May 2020 at 18:56, Lewis Ball  wrote:
>
> Joao S. O. Bueno wrote:
> > Here -  with the current inspect.Signature, it is straightforward
> > to get a decorator that can do that covering most, if not all,
> > corner cases, and even adding some extra functionality:
> > https://gist.github.com/jsbueno/f689a181d50384f627b43b9b2aabe4f2
> >
> > from inspect import signature, Parameter
> > from functools import wraps, partial
> >
> > def autoassign(func=None, *, expand_kwargs=False):
> >
> > if not func:
> > return partial(autoassign, expand_kwargs=expand_kwargs)
> > sig = signature(func)
> > @wraps(func)
> > def wrapper(*args, **kwargs):
> > instance = args[0]
> > bound_args = sig.bind(*args, **kwargs)
> > bound_args.apply_defaults()
> > for i, (key, value) in enumerate(bound_args.arguments.items()):
> > if i == 0 or sig.parameters[key].kind == 
> > Parameter.POSITIONAL_ONLY:
> > continue
> > if expand_kwargs and sig.parameters[key].kind ==
> > Parameter.VAR_KEYWORD:
> > for kwkey, kwvalue in value.items():
> > setattr(instance, kwkey, kwvalue)
> > continue
> > setattr(instance, key, value)
> > return func(*args, **kwargs)
> > return wrapper
> >
> > """
> > class A:
> > @autoassign
> > def __init__(self, a, b, c=3):
> > pass
> >
> > a = A(1, 2)
> > assert a.a == 1 and a.b == 2 and a.c == 3
> > """
>
> Is there a good reason to exclude positional only args from this? I imagine 
> if you are passing them to init you still want them to be treated internally 
> in the same way as the other args.


I think he idea of positional only args is that you don't want whoever
is calling you to care about
the variable names they will have inside your code whatsoever.
If you don't care about the name - (ideally, introspection tools
should even hide this name, if they have
a suitable notation) - you can't care about the attribute that is
created.  Even if they are to be stored
as passed in attributes, the semantics for them would be of "private"
attributes - for which
one can do the assignment manually.

>
> > Could we put this into the standard library, so that IDEs and linters are
> > programmed to recognise it?

Some people on this thread seem to have liked this approach - of course
I'd like and help getting this into the stdlib if it has support.

And yes, you come to an interesting point there - while this could
easily rest in
pypi - linters and ide's might complain about "attributes not  being
assigned in __init__"
Otherwise, I can get a Pypi package with this, and a few other bells
and whistles along.
>
> I agree, without this being recognised by linters/IDEs any attrs will show 
> with ugly warnings which would stop anyone from using it.
> ___
> 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/IMBONGILTSVKQ6JXYU3PEEN5XY4ICD5K/
> 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/4ADWBAY6AGIXG4K5XUUXDBMLZ7RE3PLL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] zip() as a class constructor (meta) [was: ... Length-Checking To zip]

2020-05-07 Thread Stephen J. Turnbull
Christopher Barker writes:

 > But though Python blurs the lines between various callables and
 > functions, there is a general "sense" of how they are used. And for
 > the most part, zip is not used like a class. WE "use" classes,
 > usually, by creating instances, and then calling various methods on
 > them, etc.

I think this is a distinction without a difference at the margin.  In
the end, all callables return objects, aka instances.  The class
*statement* is special, of course (although to me it's remarkable how
little is special about it).  But then consider factory functions.
>From the outside, what's special about them is that conventionally
they always return objects from a specific class, and that's why they
get a special name.  These distinctions are very useful to humans
thinking about a program (well, they are to me!), but they're fuzzy.

So of course zip can be said to be used like a class.  Its instances
are constructed by calling it, the most common (only in practice?) 
method call is .__iter__, it's invariably called implicitly in a for
statement, and usually the instance is ephemeral (ie, discarded when
the for statement is exited).  But it needn't be.  Like any iterator,
if it's not exhausted in one iteration context, you can continue it
later.  Or explicitly call next on it.

 > a zip instance on the other hand, returns an iterable, that does not
 > provide any other methods or uses.

A zip instance *is* an iterator (though that's not in its name), and
it has quite a few methods ;-) as you can check with dir().  In
particular it has __next__.

 > So while yes, alternate constructors are a common pattern, I don't
 > think they are a common pattern for classes like zip.

That's a matter of programming style, I think.  There's no real
difference between

zip(a, b, length='checksame')

and 

zip.checksame(a, b)

They just initialize an internal attribute differently, which may as
well be an Enum or even a few named class constants.

I think (after the initial shock ;-) I like the latter *better*,
because the semantics of checksame and longest are significantly (to
me, anyway) different.  checksame is a constraint on correct behavior,
and explicitly elicits an Exception on invalid input.  longest is a
variant specification of behavior on a certain class of valid input.
I'm happier with those being different *functions* rather than values
of an argument.  YMMV, of course.

There's another possibility, as well:

zip(a,b).checksame()

but this is bad style IMO (it would have to return self or you
couldn't "for pair in zip(a,b).checksame()", and I don't like methods
that both mutate an object and return self, though some folks do).
___
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/RGVBHDRXZOQO2KJOLSO2TSQCEKUEQLKX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: zip() as a class constructor (meta) [was: ... Length-Checking To zip]

2020-05-07 Thread Dominik Vilsmeier

On 07.05.20 09:38, Stephen J. Turnbull wrote:


Christopher Barker writes:

  > So while yes, alternate constructors are a common pattern, I don't
  > think they are a common pattern for classes like zip.

That's a matter of programming style, I think.  There's no real
difference between

 zip(a, b, length='checksame')

and

 zip.checksame(a, b)

They just initialize an internal attribute differently, which takes
one of a very few values.


The big difference between these two versions is about usability. A flag
is convenient if the actual value is expected to be determined only at
runtime so you can write `zip(a, b, length=length)`. A distinct function
on the other hand emphasizes the expectation that this behavior is
usually determined when the code is written; it would be awkward to
write `getattr(zip, length)(a, b)`. Both this and the different behavior
of zip-flavors speak in favor of the second, `zip.` version. One
concern however is that `zip.checksame` looks like `checksame` is a
convenience function of `zip` that doesn't necessarily perform any
zipping; it could only perform the length check and return True or
False. Sure, for general iterators this would not be very useful because
they get consumed in the process but for someone who doesn't know the
details this might not be as obvious. Maybe people start writing code
like this:

    if not zip.checksame(a, b):
    raise ValueError()
    for stuff in zip(a, b):
    ...
___
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/VOLDNSQUXHCDYTPUQZBBMBKNZE7HKCFJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Oscar Benjamin
On Thu, 7 May 2020 at 08:54, Greg Ewing  wrote:
>
> On 7/05/20 1:07 pm, David Mertz wrote:
> > For *most* functions, the substitution
> > principle is fine in Python.  A whole lot of the time, numeric functions
> > can take either an int or a float that are equal to each other and
> > produce results that are equal to each other.
>
> It's not much use for deciding whether two things *should* be
> equal, though, because whatever your opinion on the matter,
> you can come up with a set of functions that satisfy it and
> then say "those are the kinds of functions I mean".
>
> Also, as a definition of equality it seems somewhat circular,
> since if you're not sure whether x == y, you may be equally
> uncertain whether f(x) == f(y) for some f, x, y.

It's not so much a definition of equality as a consistency
requirement. The contrapositive can be very clear: if you already know
that f(x) and f(y) do different things or return unequal objects then
the question of whether x == y is answered.

It's important though that it's not just about equality of return
types: when you carry the principle over from maths to programming
then you need to consider non-pure functions, IO, exceptions being
raised etc.

In simple situations it is nice to be able to duck-type over lists and
tuples but in practice it has to be done carefully by sticking to the
sequence or iterable interfaces precisely or by coercing to a known
type at the entry points of your code. Once you have a large codebase
with lots of objects flying around internally and you no longer know
whether anything is a list or a tuple (or a set...) any more it's just
a mess.


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/S3U4VNQERUGNWNOMGA3LBKXWBNBBVUVZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Dominik Vilsmeier

On 07.05.20 11:11, Steven D'Aprano wrote:


On Sat, May 02, 2020 at 05:12:58AM -, Ahmed Amr wrote:


Currently, when comparing a list of items to an array of the same
items for equality (==) it returns False, I'm thinking that it would
make sense to return True in that context, as we're comparing item
values and we have the same way of indexing both collections, so we
can compare item values.


Perhaps we ought to add a second "equals" operator? To avoid
bikeshedding over syntax, I'm initially going to use the ancient 1960s
Fortran syntax and spell it `.EQ.`.

[...]

We could define this .EQ. operate as *sequence equality*, defined very
roughly as:

 def .EQ. (a, b):
 return len(a) == len(b) and all(x==y for x, y in zip(a, b))


But why do we even need a new operator when this simple function does
the job (at least for sized iterables)?

How common is it to compare two objects where you cannot determine
whether one or the other is a tuple or a list already from the
surrounding context? In the end these objects must come from somewhere
and usually functions declare either list or tuple as their return type.

Since for custom types you can already define `__eq__` this really comes
down to the builtin types, among which the theoretical equality between
tuple and list has been debated in much detail but is it used in practice?
___
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/A45PRNTU63YDHSN3VMPF7HPCOUWMPWNL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Auto-assign attributes from __init__ arguments

2020-05-07 Thread Pablo Alcain
Hello everyone, I am Pablo from Argentina! This is my first email here, so
just let me know if I am missing anything that is of use in this list, such
as presenting myself. As for this topic in particular:

Although I might use it a lot (more than I would like to admit), I don't
like this feature. First of all, I think it favors not-very-pretty code,
effectively reducing the cost you pay for writing too-many-argument
functions. It'd also obfuscate the code, and here I would like to quote the
Zen of Python "explicit is better than implicit".

It looks kind of similar (I know it has nothing to do in practice, but I
think in mindset) to creating a dictionary of parameters that you pass to
the function in order to avoid writing multiple args. If you are thinking
of doing that, maybe the problem is that you are using a wrong design, and
a programming language should "punish" it somehow.



On Wed, May 6, 2020 at 6:55 PM Lewis Ball  wrote:

> Joao S. O. Bueno wrote:
> > Here -  with the current inspect.Signature, it is straightforward
> > to get a decorator that can do that covering most, if not all,
> > corner cases, and even adding some extra functionality:
> > https://gist.github.com/jsbueno/f689a181d50384f627b43b9b2aabe4f2
> >
> > from inspect import signature, Parameter
> > from functools import wraps, partial
> >
> > def autoassign(func=None, *, expand_kwargs=False):
> >
> > if not func:
> > return partial(autoassign, expand_kwargs=expand_kwargs)
> > sig = signature(func)
> > @wraps(func)
> > def wrapper(*args, **kwargs):
> > instance = args[0]
> > bound_args = sig.bind(*args, **kwargs)
> > bound_args.apply_defaults()
> > for i, (key, value) in enumerate(bound_args.arguments.items()):
> > if i == 0 or sig.parameters[key].kind ==
> Parameter.POSITIONAL_ONLY:
> > continue
> > if expand_kwargs and sig.parameters[key].kind ==
> > Parameter.VAR_KEYWORD:
> > for kwkey, kwvalue in value.items():
> > setattr(instance, kwkey, kwvalue)
> > continue
> > setattr(instance, key, value)
> > return func(*args, **kwargs)
> > return wrapper
> >
> > """
> > class A:
> > @autoassign
> > def __init__(self, a, b, c=3):
> > pass
> >
> > a = A(1, 2)
> > assert a.a == 1 and a.b == 2 and a.c == 3
> > """
>
> Is there a good reason to exclude positional only args from this? I
> imagine if you are passing them to init you still want them to be treated
> internally in the same way as the other args.
>
> > Could we put this into the standard library, so that IDEs and linters are
> > programmed to recognise it?
>
> I agree, without this being recognised by linters/IDEs any attrs will show
> with ugly warnings which would stop anyone from using it.
> ___
> 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/IMBONGILTSVKQ6JXYU3PEEN5XY4ICD5K/
> 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/C54WVBCSL5ID4XD5MYGLOSK6V24EYHWN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Adding a "once" function to functools

2020-05-07 Thread toms . highonstudy
The connection is very obvious after you know about it.
And probably you can guess the meaning if you see an
@once decorator in someone's code. But it's less clear
that a person who hasn't seen the word "once" used
this way will think of searching for it when they want
a way to cache the return value of a function. 
https://docs.python.org/3/library/functools.html#functools.lru_cache
___
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/TQJD6QDVYJA5LOAJ3C2V3BJ5MRFSD3OA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Steven D'Aprano
On Thu, May 07, 2020 at 01:17:37PM +0100, Henk-Jaap Wagenaar wrote:

> Why use "." which has clear syntax problems?

[Me]
> > (For the avoidance of doubt, I know that syntax will not work in 
> > Python because it will be ambiguous. That's why I picked it -- it's 
> > syntax that we can all agree won't work, so we can concentrate on 
> > the semantics not the spelling.)


[Henk-Jaap]
> This can already be done in current Python (this was linked to in a
> previous thread about something else) using a generic solution if you
> change the syntax:
> 
> https://pypi.org/project/infix/
> 
> You could write it as |EQ|, ^EQ^, ... and have it in its own Pypi package.

That's a gimmick and a hack. To be sure, it's a cute hack, but not one I 
would ever use in real code.


-- 
Steven
___
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/JIZ6ULR5PGWFLHR7KTNKXSZSSSUNC5NF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Henk-Jaap Wagenaar
Why use "." which has clear syntax problems?

This can already be done in current Python (this was linked to in a
previous thread about something else) using a generic solution if you
change the syntax:

https://pypi.org/project/infix/

You could write it as |EQ|, ^EQ^, ... and have it in its own Pypi package.

Not sure what IDEs think of this package, they probably hate it...

On Thu, 7 May 2020 at 10:18, Steven D'Aprano  wrote:

> On Sat, May 02, 2020 at 05:12:58AM -, Ahmed Amr wrote:
>
> > Currently, when comparing a list of items to an array of the same
> > items for equality (==) it returns False, I'm thinking that it would
> > make sense to return True in that context, as we're comparing item
> > values and we have the same way of indexing both collections, so we
> > can compare item values.
>
> I'm going to throw out a wild idea (actually not that wild :-) that I'm
> sure people will hate for reasons I shall mention afterwards.
>
> Perhaps we ought to add a second "equals" operator? To avoid
> bikeshedding over syntax, I'm initially going to use the ancient 1960s
> Fortran syntax and spell it `.EQ.`.
>
> (For the avoidance of doubt, I know that syntax will not work in Python
> because it will be ambiguous. That's why I picked it -- it's syntax that
> we can all agree won't work, so we can concentrate on the semantics not
> the spelling.)
>
> We could define this .EQ. operate as *sequence equality*, defined very
> roughly as:
>
> def .EQ. (a, b):
> return len(a) == len(b) and all(x==y for x, y in zip(a, b))
>
> (Aside: if we go down this track, this could be a justification for
> zip_strict to be a builtin; see the current thread(s) on having a
> version of zip which strictly requires its input to be equal length.)
>
> The precise details of the operator are not yet clear to me, for
> instance, should it support iterators or just Sized iterables? But at
> the very least, it would support the original request:
>
> [1, 2, 3] .EQ. (1, 2, 3)
> # returns True
>
>
> The obvious operator for this would be `===` but of course that will
> lead to an immediate and visceral reaction "Argghhh, no, Javascript, do
> not want!!!" :-)
>
> Another obvious operator would be a new keyword `eq` but that would
> break any code using that as a variable.
>
> But apart from the minor inconveniences that:
>
> - I don't know what this should do in detail, only vaguely;
> - and I have no idea what syntax it should have
>
> what do people think of this idea?
>
>
> --
> Steven
> ___
> 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/JP3BXZLQRQYHGSB4KOX2K5TLP6A6PLR2/
> 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/LVVAQQYY7SYM7M5MGER5DVRVQ2NTMH3O/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Steven D'Aprano
On Thu, May 07, 2020 at 10:44:01PM +1200, Greg Ewing wrote:
> On 7/05/20 9:11 pm, Steven D'Aprano wrote:
> >I'm initially going to use the ancient 1960s
> >Fortran syntax and spell it `.EQ.`.
> >
> >I know that syntax will not work in Python
> >because it will be ambiguous.
> 
> I'm sure the new parser will handle it just fine!

Yes, but the *human readers* won't. You know that people will write 
things like:

spam.EQ.ham

and then nobody will know whether than means "call the .EQ. operator on 
operands spam and ham" or "lookup the ham attribute on the EQ attribute 
of spam" without looking up the parsing rules.

Let's not turn into Ruby:

https://lucumr.pocoo.org/2008/7/1/whitespace-sensitivity/


-- 
Steven
___
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/TXEYLN6ZUKFX7B4VTW5XRM3VML6CQ5BJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Steven D'Aprano
On Thu, May 07, 2020 at 06:04:13AM -0400, Dan Sommers wrote:
> On Thu, 7 May 2020 19:11:43 +1000
> Steven D'Aprano  wrote:
> 
> > We could define this .EQ. operate as *sequence equality*, defined very
> > roughly as:
> > 
> > def .EQ. (a, b):
> > return len(a) == len(b) and all(x==y for x, y in zip(a, b))
> 
> Equality and its awkward cousin equivalence are slippery slopes.  Just
> sequences?  That (admittedly rough) function returns true for certain
> mapping arguments.

*shrug*

As I point out later in my post, I don't know whether it should be just 
sequences. Maybe it should be any iterable, although checking them for 
equality will necessarily consume them. But *right now* the proposal on 
the table is to support list==tuple comparisons, which this would do.

(For an especially vague definition of "do" :-)


> What about case-insensitive string matching?

That can be a string method, since it only needs to operate on strings.


> The strongest equality is the "is" operator

Please don't encourage the conceptual error of thinking of `is` as 
*equality*, not even a kind of equality. It doesn't check for equality, 
it checks for *identity* and we know that there is at least one object 
in Python where identical objects aren't equal:

py> from math import nan
py> nan is nan
True
py> nan == nan
False


[...]
> The very far ends of that scale are glossing over American
> vs. British spellings (are "color" and "colour" in some sense equal?),

YAGNI.

The proposal here is quite simple and straightforward, there is no need 
to over-generalise it to the infinite variety of possible equivalencies 
than someone might want. People can write their own functions.

It is only that wanting to compare two ordered containers for equality 
of their items without regard to the type of container is a reasonably 
common and useful thing to do.

Even if we don't want list==tuple to return True -- and I don't! -- we 
surely can recognise that sometimes we don't care about the container's 
type, only it's elements.


-- 
Steven
___
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/X7GJ3U7Z6ODD2DO6JWZKZ453TJZKJPFY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: zip(x, y, z, strict=True)

2020-05-07 Thread Steven D'Aprano
On Wed, May 06, 2020 at 08:48:51AM -0700, Christopher Barker wrote:

[I asked]
> > A ternary flag of strict = True, False or what?
> >
> 
> Come on:
> 
> ternary: having three elements, parts, or divisions (
> https://www.merriam-webster.com/dictionary/ternary)
> 
> did you really not know that? 

Of course I know what ternary is.


> (and "flag" does not always mean "boolean
> flag", even thoughit often does (https://techterms.com/definition/flag) )

I am arguing against the proposal being discussed in this part of the 
thread, namely to add a **boolean** flag "strict=True|False".

Then if we want to extend the API in the future, you say "Oh well that's 
easy, let's just turn it into a ternary flag" (paraphrasing, not a 
direct quote). Okay, so what will the third flag be? Standard ternary 
flags are:

True, False, Maybe
True, False, Unknown

Neither Maybe nor Unknown are Python builtins. Should they be? I doubt 
it. So what do we use? Whenever I've needed ternary logic, I've 
used None. But in this case, that doesn't work:

zip(*iters, strict=None)

What a very non-self-explanatory API.

So if we start off with a `strict=bool` API, we're stuck with it.


> This has been proposed multiple times on this list:
> 
> a flag that takes three possible values: "shortest" | "longest" | "equal"
> (defaulting to shortest of course). Name to be bikeshed later :-)
> (and enum vs string also to be bikeshed later)

*Named modes* are not typically called flags. For example, the second 
parameter to `open` is called *mode*, not *flag*.

Whether or not a named mode parameter has been proposed before, that's 
not what is being discussed here and now, where we have been explicitly 
debating the two APIs:

- a named function;
- piggy-backing on zip() with a **boolean parameter** taking True and
  False as the switch to control behaviour.

so in the context of the discussion about bool parameters, other APIs 
aren't really relevant. I'm arguing agains the specific `strict=bool` 
API, not other APIs in general. Revamping zip to give it a named mode 
parameter is not my first preference, but it's better than a 
`strict=bool` flag.

However the parameter would have to change:

zip(*iters, strict="shortest")

simply doesn't work.


> > This demonstrates why the "constant flag" is so often an 
> > antipattern. It doesn't scale past two behaviours. Or you end up 
> > with a series of flags:
> >
> > zip(*iterators, strict=False, longest=False, fillvalue=None)
> >
> 
> I don't think anyone proposed an API like that -- yes, that would be horrid.

I do recall someone proposing something similar to that, but I don't 
care enough to trawl through the thread to find it :-)


> There are all sorts of reasons why a ternary flag would not be good, but I
> do think it should be mentioned in the PEP, even if only as a rejected idea.
> 
> But I still like it, 'cause the "flag for two behaviors and another
> function for the third" seem sliek the worse of all options.

*blink*

But that's precisely the option on the table right now!

1. zip_longest remains in itertools;
2. zip remains the default behaviour;
3. zip_strict be implemented as a boolean True/False parameter on zip.

I trust you don't actually mean what you seem to be saying: "this is the 
worst of all options, I'm in favour of it!"

But in any case, I see from a later part of the discussion we're now 
considering a different option:

- treat zip as a namespace, with named callable attributes

which I don't dislike.


-- 
Steven
___
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/MEY2FNXI6NDAOIQLI7KGE7LR5A5GSANH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Greg Ewing

On 7/05/20 9:11 pm, Steven D'Aprano wrote:

I'm initially going to use the ancient 1960s
Fortran syntax and spell it `.EQ.`.

I know that syntax will not work in Python
because it will be ambiguous.


I'm sure the new parser will handle it just fine!

--
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/4V7EGQPTWSKIRLOBZ3OLZTSCOVJAF5RG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Dan Sommers
On Thu, 7 May 2020 19:11:43 +1000
Steven D'Aprano  wrote:

> We could define this .EQ. operate as *sequence equality*, defined very
> roughly as:
> 
> def .EQ. (a, b):
> return len(a) == len(b) and all(x==y for x, y in zip(a, b))

Equality and its awkward cousin equivalence are slippery slopes.  Just
sequences?  That (admittedly rough) function returns true for certain
mapping arguments.

What about case-insensitive string matching?  Is that more common than
comparing (or wanting to compare) arbitrary sequences?  What about an
operator for normalized (in the Unicode sense of the word),
case-insensitive string comparison?  (There's a precedent:  Common
Lisp's equalp function does case-insensitive string matching.)

The strongest equality is the "is" operator, and then the == operator,
and ISTM that you're now extending this idea to another class of
equivalency.  The very far ends of that scale are glossing over American
vs. British spellings (are "color" and "colour" in some sense equal?),
or even considering two functions "the same" if they produce the same
outputs for the same inputs.

One of Python's premises and strengths is strong typing; please don't
start pecking away at that.  Do beginners expect that [1, 2, 3] == (1,
2, 3)?  No.  Do experts expect that [1, 2, 3] == (1, 2, 3)?  No.  So who
does?  Programmers working on certain applications, or with multiple
[pre-existing] libraries, or without a coherent design.

These all seem like appliction level (or even design level) problems, or
maybe a series of dunder methods / protocols to define various levels of
equivalence (the ability of my inbox and my brain to handle the
resulting bikeshedding notwithstanding).  YMMV.

Just my thoughts.

-- 
“Atoms are not things.” – Werner Heisenberg
Dan Sommers, http://www.tombstonezero.net/dan
___
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/CEJXL3MZRETWH5RHJABKBE27Q74TTSPY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 618: Add Optional Length-Checking To zip

2020-05-07 Thread Steven D'Aprano
On Wed, May 06, 2020 at 09:17:15PM -0400, Eric V. Smith wrote:

> I think David is right: itertools.chain.from_iterable() is the only 
> place I know of with an attribute on a function that's another function.

Functions decorated with `functools.wrap` have an attribute that gives 
the original function:

py> def f(): return True
...
py> g = wraps(f)(lambda: False)
py> g()
False
py> g.__wrapped__()
True

Likewise `functools.partial` objects have a `func` attribute that gives 
the original function:

py> h = partial(lambda a, b: a + b)
py> h = partial(lambda a, b: a + b, 1000)
py> h(1)
1001
py> h.func(1, 2)
3

Functions which have been decorated with lru_cache are given two 
function attributes, `cache_clear` and `cache_info`.

I believe that there is also an example in mock, but I don't remember 
the details.

I wanted to use this attributes on the median() function in the 
statistics module to spell the less-important variations:

median()  # standard version as taught in schools

with the specialist versions as attributes:

median.lower()
median.upper()

but I was talked out of it in favour of three separate functions:

median, median_lower, median_upper

I still regret giving in on this point. IMO the lower and upper medians 
are useful but not important enough to be top-level functions.


"Namespaces are one honking great idea -- let's do more of those!"

Functions are namespaces! They have internal `__dicts__` and can hold 
arbitrary attributes. Why are we so reluctant to follow the Zen and use 
those namespaces?

 
> Alternate constructors are generally classmethods.

The fact that chain.from_iterable is, in a sense, an alternative 
constructor is an implementation detail. `chain` happens to be a class 
that returns an instance of `chain`, but it could have simply returned a 
generic generator, or some other kind of instance.

> And it's the documentation that I'm concerned about: I don't think 
> itertools.chain.from_iterable() is very discoverable. Plenty of people 
> don't know it exists. That's my concern with this approach.

It isn't hard to add a "See also..." line to the chain docstring 
pointing to the existence of chain.from_iterable, and we should do that.

Also, help() should be enhanced to give better support for function 
attributes.

Your point about discoverability is taken, but it is no less 
discoverable than other namespaces. If I know a package:

import package
package.function(arg)

that knowledge doesn't give me any insight into any subpackages that I 
haven't imported and may not even know about:

# How do I learn to do this?
from package.subpackage import anotherfunction



-- 
Steven
___
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/QTDBXD733BL2AFYG7V6IPAJ5BG7T42VF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Alex Hall
This reminded me of another recent message so I decided to find that and
link it here:
https://mail.python.org/archives/list/python-ideas@python.org/message/7ILSYYOFPQL5DVH5DGIGQSL6PYFYF7PC/

It seemed like a more useful thing to do before I discovered that you wrote
that too...

On Thu, May 7, 2020 at 11:20 AM Steven D'Aprano  wrote:

> On Sat, May 02, 2020 at 05:12:58AM -, Ahmed Amr wrote:
>
> > Currently, when comparing a list of items to an array of the same
> > items for equality (==) it returns False, I'm thinking that it would
> > make sense to return True in that context, as we're comparing item
> > values and we have the same way of indexing both collections, so we
> > can compare item values.
>
> I'm going to throw out a wild idea (actually not that wild :-) that I'm
> sure people will hate for reasons I shall mention afterwards.
>
> Perhaps we ought to add a second "equals" operator? To avoid
> bikeshedding over syntax, I'm initially going to use the ancient 1960s
> Fortran syntax and spell it `.EQ.`.
>
> (For the avoidance of doubt, I know that syntax will not work in Python
> because it will be ambiguous. That's why I picked it -- it's syntax that
> we can all agree won't work, so we can concentrate on the semantics not
> the spelling.)
>
> We could define this .EQ. operate as *sequence equality*, defined very
> roughly as:
>
> def .EQ. (a, b):
> return len(a) == len(b) and all(x==y for x, y in zip(a, b))
>
> (Aside: if we go down this track, this could be a justification for
> zip_strict to be a builtin; see the current thread(s) on having a
> version of zip which strictly requires its input to be equal length.)
>
> The precise details of the operator are not yet clear to me, for
> instance, should it support iterators or just Sized iterables? But at
> the very least, it would support the original request:
>
> [1, 2, 3] .EQ. (1, 2, 3)
> # returns True
>
>
> The obvious operator for this would be `===` but of course that will
> lead to an immediate and visceral reaction "Argghhh, no, Javascript, do
> not want!!!" :-)
>
> Another obvious operator would be a new keyword `eq` but that would
> break any code using that as a variable.
>
> But apart from the minor inconveniences that:
>
> - I don't know what this should do in detail, only vaguely;
> - and I have no idea what syntax it should have
>
> what do people think of this idea?
>
>
> --
> Steven
> ___
> 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/JP3BXZLQRQYHGSB4KOX2K5TLP6A6PLR2/
> 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/CL3D27XE7K2HYV6IN5M5DPVIU7XXS7B2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Steven D'Aprano
On Sat, May 02, 2020 at 05:12:58AM -, Ahmed Amr wrote:

> Currently, when comparing a list of items to an array of the same 
> items for equality (==) it returns False, I'm thinking that it would 
> make sense to return True in that context, as we're comparing item 
> values and we have the same way of indexing both collections, so we 
> can compare item values.

I'm going to throw out a wild idea (actually not that wild :-) that I'm 
sure people will hate for reasons I shall mention afterwards.

Perhaps we ought to add a second "equals" operator? To avoid 
bikeshedding over syntax, I'm initially going to use the ancient 1960s 
Fortran syntax and spell it `.EQ.`.

(For the avoidance of doubt, I know that syntax will not work in Python 
because it will be ambiguous. That's why I picked it -- it's syntax that 
we can all agree won't work, so we can concentrate on the semantics not 
the spelling.)

We could define this .EQ. operate as *sequence equality*, defined very 
roughly as:

def .EQ. (a, b):
return len(a) == len(b) and all(x==y for x, y in zip(a, b))

(Aside: if we go down this track, this could be a justification for 
zip_strict to be a builtin; see the current thread(s) on having a 
version of zip which strictly requires its input to be equal length.)

The precise details of the operator are not yet clear to me, for 
instance, should it support iterators or just Sized iterables? But at 
the very least, it would support the original request:

[1, 2, 3] .EQ. (1, 2, 3)
# returns True


The obvious operator for this would be `===` but of course that will 
lead to an immediate and visceral reaction "Argghhh, no, Javascript, do 
not want!!!" :-)

Another obvious operator would be a new keyword `eq` but that would 
break any code using that as a variable.

But apart from the minor inconveniences that:

- I don't know what this should do in detail, only vaguely;
- and I have no idea what syntax it should have

what do people think of this idea?


-- 
Steven
___
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/JP3BXZLQRQYHGSB4KOX2K5TLP6A6PLR2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: zip(x, y, z, strict=True)

2020-05-07 Thread Kirill Balunov
On Thu, May 7, 2020 at 3:07 AM Christopher Barker 
wrote:

> On Wed, May 6, 2020 at 1:42 PM Kirill Balunov 
> wrote:
>
>> I'm totally agree with everything you said here. From my perspective,
>> comparing three main cases:
>> 1. zip(*iters, strict= (False | True))
>> 2. zip(*iters, mode = ('shortest' | 'equal' | 'longest'))
>> 3. zip_equal(*iters)
>>
>
> Thanks for enumerating these. I think that's helpful so I'll flesh it out
> a bit more. I *think* these are the options on the table:
>
> (note, I'm keeping different names for things as the same option, and in
> no particular order)
>
> 1) No change
> zip(*iters)
> itertools.zip_longest(*iters, fillvalue=None)
>
> 2) Add boolean strict flag to zip
> zip(*iters, strict= (False | True))
> itertools.zip_longest(*iters, fillvalue=None)
>
> 3) Add a ternary mode flag to zip
> zip(*iters, mode = ('shortest' | 'equal' | 'longest'), fillvalue=None)
>
> 4) Add a new function to itertools
> zip(*iters)
> itertools.zip_longest(*iters, fillvalue=None)
> itertools.zip_equal(*iters)
>
>
I think there are two more cases which can be added to the list:

0) No change
zip(*iters)
itertools.zip_longest(*iters, fillvalue=None)
+ add a recipe about zip_equal in itertools docs

6) Add functionality through  zip methods (as proposed in a separate
thread, but maybe it is off topic for the current thread).

-gdg
___
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/ZBGIGXWL2PZY6H2JWU6UZOPHVBMUE6HW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 618: Add Optional Length-Checking To zip

2020-05-07 Thread Kirill Balunov
On Thu, May 7, 2020 at 10:56 AM Alex Hall  wrote:

> On Thu, May 7, 2020 at 9:48 AM Kirill Balunov 
> wrote:
>
>> Sorry for off topic. Isn't this chain.from_iterable just a historical
>> legacy... now we have PEP 448 and I see no differences* between
>> chain(*iterable) vs chain.from_iterable(iterable). Are there?
>>
>> * chain.from_iterable is a little bit faster for small iterables, but if
>> at that time we had PEP 448, would this small speed benefits be enough to
>> make additional method to chain. I think no.
>>
>> -gdg
>>
>
> `chain(*iterable)` converts iterable into a tuple, concretizing it in
> memory. chain.from_iterable(iterable) is lazy and goes through the elements
> one a time, meaning iterable can be infinite.
>
> I don't think PEP 448 has any bearing on that.
>

Heh, surely, I misunderstood the point of PEP 448, and checked that it was
also possible in Python 2.

"meaning iterable can be infinite"  -  thank you, I missed this part, but
to be honest I don’t remember when I do something useful with
infinite iterables.

-gdg
___
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/EC3XT7CUC5EZ2DGC24DLTKFOGCLJQH5A/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 618: Add Optional Length-Checking To zip

2020-05-07 Thread Alex Hall
On Thu, May 7, 2020 at 9:48 AM Kirill Balunov 
wrote:

> Sorry for off topic. Isn't this chain.from_iterable just a historical
> legacy... now we have PEP 448 and I see no differences* between
> chain(*iterable) vs chain.from_iterable(iterable). Are there?
>
> * chain.from_iterable is a little bit faster for small iterables, but if
> at that time we had PEP 448, would this small speed benefits be enough to
> make additional method to chain. I think no.
>
> -gdg
>
>> 
>
>
`chain(*iterable)` converts iterable into a tuple, concretizing it in
memory. chain.from_iterable(iterable) is lazy and goes through the elements
one a time, meaning iterable can be infinite.

I don't think PEP 448 has any bearing on that.
___
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/KPNW3MRWKNJ3PYR55YWHCPP5J6J5V3L6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Greg Ewing

On 7/05/20 1:07 pm, David Mertz wrote:
For *most* functions, the substitution 
principle is fine in Python.  A whole lot of the time, numeric functions 
can take either an int or a float that are equal to each other and 
produce results that are equal to each other.


It's not much use for deciding whether two things *should* be
equal, though, because whatever your opinion on the matter,
you can come up with a set of functions that satisfy it and
then say "those are the kinds of functions I mean".

Also, as a definition of equality it seems somewhat circular,
since if you're not sure whether x == y, you may be equally
uncertain whether f(x) == f(y) for some f, x, y.

--
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/IRMSHU36L6QQBHZ35DPRHE5DTZ54U7AG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: PEP 618: Add Optional Length-Checking To zip

2020-05-07 Thread Kirill Balunov
Sorry for off topic. Isn't this chain.from_iterable just a historical
legacy... now we have PEP 448 and I see no differences* between
chain(*iterable) vs chain.from_iterable(iterable). Are there?

* chain.from_iterable is a little bit faster for small iterables, but if at
that time we had PEP 448, would this small speed benefits be enough to make
additional method to chain. I think no.

-gdg

On Thu, May 7, 2020 at 3:24 AM David Mertz  wrote:

> The only precedent that jumps out for me is itertools.chain() and
> itertools.chain.from_iterable(). It's quite likely that something I don't
> use much has used the same pattern though.
>
> On Wed, May 6, 2020, 8:17 PM Christopher Barker 
> wrote:
>
>> On Wed, May 6, 2020 at 10:31 AM Alex Hall  wrote:
>> zip.shortest(...)  # same as zip(...)
>> zip.longest(...)
>> zip.checksame(...)
>>
>> I presume that zip() would keep its current behavior, yes?
>>
>> I kind of like this -- is there any precedent for it in the standard
>> library?
>>
>> The PEP seems to reject this saying:
>>
>> The actual zip type is an undocumented implementation detail. Adding
>>> additional methods or constructors is really a much larger change that is
>>> not necessary to achieve the stated goal.
>>
>>
>> well, yes and no -- the first part indicates that we could totally change
>> the type of the zip, as long as it's a collable that returns an iterator.
>>
>> Whether adding additional methods is too large a change -- that's totally
>> a matter of opinion.
>>
>> > Having these alternative 'methods' would be similar to having different
>> functions in itertools,
>> indeed -- same idea, different namepace.
>>
>> -CHB
>>
>> --
>> Christopher Barker, PhD
>>
>> 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/5EC4BLXEUZWEE2D7PP43WK6BAGEVFRPB/
>> 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/3BOXVZKFRF7APL5IRBWXQSQOLQWTMBPW/
> 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/EUV4TEJWNLVR6V3AJXHXNPFSDG7WTHVK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Alex Hall
On Thu, May 7, 2020 at 2:33 AM Oscar Benjamin 
wrote:

> On Sat, 2 May 2020 at 20:50, Serhiy Storchaka  wrote:
> >
> > 02.05.20 21:34, Ahmed Amr пише:
> > > I see there are ways to compare them item-wise, I'm suggesting to bake
> > > that functionality inside the core implementation of such indexed
> > > structures.
> > > Also those solutions are direct with tuples and lists, but it wouldn't
> > > be as direct with arrays-lists/tuples comparisons for example.
> >
> > If make `(1, 2, 3) == [1, 2, 3]` we would need to make `hash((1, 2, 3))
> > == hash([1, 2, 3])`.
>
> This is the key point. Much of the other discussion in this thread
> seems to be bogged down in the mathematical interpretation of tuples
> and sequences but if I was to take something from maths here it would
> be the substitution principle of equality:
> https://en.wikipedia.org/wiki/Equality_(mathematics)#Basic_properties
>
> What the substitution principle essentially says is
>if x == y then f(x) == f(y)
> for any function f such that f(x) is well defined.
>
> What that means is that I should be able to substitute x for y in any
> context where x would work without any change of behaviour.


We discussed this and Dominik pointed out that set and frozenset already
break this property, specifically for hash(). Do you think frozensets and
normal sets should never be equal?
___
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/RSHTLMOA3GOL2G7EA233HEX4YMGH5Y2A/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] zip() as a class constructor (meta) [was: ... Length-Checking To zip]

2020-05-07 Thread Stephen J. Turnbull
Christopher Barker writes:

 > But though Python blurs the lines between various callables and
 > functions, there is a general "sense" of how they are used. And for
 > the most part, zip is not used like a class. WE "use" classes,
 > usually, by creating instances, and then calling various methods on
 > them, etc.

I think this is a distinction without a difference at the margin.  In
the end, all callables return objects, aka instances.  The class
*statement* is special, of course (although to me it's remarkable how
little is special about it).  But then consider factory functions.
>From the outside, what's special about them is that conventionally
they always return objects from a specific class, and that's why they
get a special name.  These distinctions are very useful to humans
thinking about a program (well, they are to me!), but they're fuzzy.

So of course zip can be said to be used like a class.  Its instances
are constructed by calling it, the most common (only in practice?) 
method call is .__iter__, it's invariably called implicitly in a for
statement, and usually the instance is ephemeral (ie, discarded when
the for statement is exited).  But it needn't be.  Like any iterator,
if it's not exhausted in one iteration context, you can continue it
later.  Or explicitly call next on it.

 > a zip instance on the other hand, returns an iterable, that does not
 > provide any other methods or uses.

A zip instance *is* an iterator (though that's not in its name), and
it has quite a few methods ;-) as you can check with dir().  It's just
that the three most interesting ones (__init__, __iter__, and
__next__) are invariably invoked implicitly.

 > So while yes, alternate constructors are a common pattern, I don't
 > think they are a common pattern for classes like zip.

That's a matter of programming style, I think.  There's no real
difference between

zip(a, b, length='checksame')

and 

zip.checksame(a, b)

They just initialize an internal attribute differently, which takes
one of a very few values.

I think (after the initial shock ;-) I like the latter *better*,
because the semantics of checksame and longest are significantly (to
me, anyway) different.  checksame is a constraint on correct behavior,
and explicitly elicits an Exception on invalid input.  longest is a
variant specification of behavior on a certain class of valid input.
I'm happier with those being different *functions* rather than values
of an argument.  YMMV, of course.

There's another possibility, as well:

zip(a,b).set_check_same()

but this is bad style IMO (it would have to return self or you
couldn't "for pair in zip(a,b).set_check_same()", and I don't like
methods that both mutate an object and return self, though some folks
do).

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/WQQJPTZ2RKK4D7KHB6EGUZCRUHQ6E4UI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Equality between some of the indexed collections

2020-05-07 Thread Chris Angelico
On Thu, May 7, 2020 at 12:26 PM Oscar Benjamin
 wrote:
>
> On Thu, 7 May 2020 at 02:07, David Mertz  wrote:
> >
> > That's the point though.  For *most* functions, the substitution principle 
> > is fine in Python.  A whole lot of the time, numeric functions can take 
> > either an int or a float that are equal to each other and produce results 
> > that are equal to each other.  Yes, I can write something that will 
> > sometimes overflow for floats but not ints.  Yes, I can write something 
> > where a rounding error will pop up differently between the types.  But 
> > generally, numeric functions are "mostly the same most of the time" with 
> > float vs. int arguments.
>
> The question is whether you (or Chris) care about calculating things
> accurately with floats or ints. If you do try to write careful code
> that calculates things for one or the other you'll realise that there
> is no way to duck-type anything nontrivial because the algorithms for
> exact vs inexact or bounded vs unbounded arithmetic are very different
> (e.g. sum vs fsum). If you are not so concerned about that then you
> might say that 1 and 1.0 are "acceptably interchangeable".
>

I most certainly DO care about accurate integer calculations, which is
one of the reasons I'm very glad to have separate int and float types
(ahem, ECMAScript, are you eavesdropping here?). In any situation
where I would consider them equivalent, it's actually the float that I
want (it's absolutely okay if I have to explicitly truncate a float to
int if I want to use it in that context), so the only way they'd not
be equivalent is if the number I'm trying to represent actually isn't
representable. Having to explicitly say "n + 0.0" to force it to be a
float isn't going to change that, so there's no reason to make that
explicit.

For the situations where things like fsum are important, it's great to
be able to grab them. For situations where you have an integer number
of seconds and want to say "delay this action by N seconds" and it
wants a float? It should be fine accepting an integer.

> Please understand though that I am not proposing that 1==1.0 should be
> changed. It is supposed to be a simple example of the knock on effect
> of defining __eq__ between non-equivalent objects.

Definitely not. I'm just arguing against your notion that equality
should ONLY be between utterly equivalent things. It's far more useful
to allow more things to be equal.

ChrisA
___
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/Z7WJPX62AJZ2RUJ2MJ62AVU2THWFZIB5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: zip(x, y, z, strict=True)

2020-05-07 Thread Paul Moore
On Thu, 7 May 2020 at 01:07, Christopher Barker  wrote:
> 3) Add a ternary mode flag to zip
> zip(*iters, mode = ('shortest' | 'equal' | 'longest'), fillvalue=None)

You missed

itertools.zip_longest(*iters, fillvalue=None)

from this one. Unless you're proposing to drop itertools.zip_longest,
the fact that there's now two ways to do zip_longest seems like an
important wart to point out for this proposal.

For me:

+0.1 on a new function in itertools
+0 on no change
-1 on the remainder

Paul
___
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/4JTJQHJICFWNUDM5P4JLDAE7JFTAZDYF/
Code of Conduct: http://python.org/psf/codeofconduct/