I would like to mention that the issue of assignment to a target list, is also relevant to the case of elementwise assignment to a mutable sequence (e.g. lists and arrays). Here as well, the rhs of the assignment statement states the number of elements to be assigned. Consequently, the following example will get into infinite loop:
>>> from itertools import count
>>> A = []
>>> A[:] = count()
Writing "A[:2] = count()" will cause the same result.
Here as well, it is currently safer to use islice if the rhs is a generator or an iterator. e.g.:
>>> it = count()
>>> A[:] = islice(it,2)
In my opinion, it is be better to devise a solution that could be applied in both cases. Maybe a new kind of assignment operator that will be dedicated to this kind of assignment. i.e. elementwise assignment with restriction on the number of elements to be assigned, based on the length of the lhs object (or the number of targets in the target list).
Would be useful to pass exception-raising lambdas around.
ensure(cond, lambda: raise TypeError())
I guess one could instead use (and raise in ensure())
ensure(cond, lambda: TypeError())
But I think exception-raising lambdas would be nicer.
I've used Python for 20 years, and programming in general for about 40 now.
I think almost EVERY large code base I've seen used asserts in their
intended way. I frequently use them myself in a way differentiated (subtly)
from 'if cond: raise SomeException'.
I honestly don't know how Ivan has avoided seeing these. Giving up this
useful construct would feel about the same as depreciating 'finally'. Yes,
Python would be Turing complete without it, and you could work around it
being missing... But why?!
On Nov 27, 2017 11:12 PM, "Ivan Pozdeev via Python-ideas" <
python-ideas(a)python.org> wrote:
On 28.11.2017 8:59, Steven D'Aprano wrote:
> On Tue, Nov 28, 2017 at 07:35:45AM +0300, Ivan Pozdeev via Python-ideas
> wrote:
>
> Actually, the way I'm using them,
>>
>> assert condition, "error message", type
>>
>> would probably be the most expressive way.
>>
> I disagree that is expressive -- I call it *misleading*. I see something
> which looks like an assertion (that is, a checked comment, a contract, a
> check on an internal piece of logic etc) but it is actually being used
> as a test.
>
>
> I can do anything in any Turing-complete language without any changes to
>> the language. That's no reason to never change anything, is it.
>>
> "We can change this" is not a reason to change this. There needs to be a
> *good* reason to change, and you have given no good reasons for this
> change.
>
>
> The rationale basically is:
>> * As it was intended, the statement has no practical use -- basically a
>> rudiment, due to disappear eventually
>>
> Nonsense. I make extensive use of assert as a way of checking
> assertions, and I will fight tooth and nail against any proposal to
> either remove it or to misuse it for public input tests instead of
> assertions.
>
I invite you to show me a single use case for those "assertions" because
after ~20 years of experience in coding (that included fairly large
projects), I've yet to see one.
Any, every check that you make at debug time either
* belongs in production as well (all the more because it's harder to
diagnose there), or
* belongs in a test -- something coded independently from the program (if
your code as a whole cannot be trusted, how any specific part of it can?),
or
* isn't needed at all because a fault will inevitably surface somewhere
down the line (as some exception or an incorrect result that a test will
catch).
Finally, I've got much experience using existing code outside its original
use cases, where the original author's assumptions may no longer hold but
the specific logic can be gauded to produce the desired result. Coding
these assumptions in would undermine that goal.
So, I see "debug assertions" as either intentionally compromizing
correctness for performance (a direct opposite of Python's design
principles), or as an inferiour, faulty, half-measure rudiment from times
when CI wasn't a thing (thus not something that should be taught and
promoted as a best practice any longer).
> * It can instead be reused as syntax sugar to cover a very common use case
>>
> There is no need for such syntactic sugar. It would be harmful
> to use assert for something which is not an assertion.
>
>
>
>
--
Regards,
Ivan
_______________________________________________
Python-ideas mailing list
Python-ideas(a)python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
Nothing so bombastic this time. The heapq functions are basically all named
"heapsomething", and basically all take a "heap" for their first argument,
with supplementary args coming after. It's a textbook example of the
(hypothetical) Object Oriented Manifesto™ where defining a class increases
type safety and programmers' conceptual clarity. There're practically no
drawbacks, and the code to be added would be very simple. Updating the
tests and docs would probably be harder.
In pure Python, such a class would look like this:
class Heap(list):
def __init__(self, iterable=None):
if iterable:
super().__init__(iterable)
else:
super().__init__()
self.heapify()
push = heapq.heappush
pop = heapq.heappop
pushpop = heapq.heappushpop
replace = heapq.heapreplace
heapify = heapq.heapify
# This could be a simple wrapper as well, but I had the following
thoughts anyways, so here they are
def nsmallest(self, n, key=None):
# heapq.nsmallest makes a *max* heap of the first n elements,
# while we know that self is already a min heap, so we can
# make the max heap construction faster
self[:n] = reversed(self[:n])
return heapq.nsmallest(n, self, key)
# do we define nlargest on a minheap??
Wrapping around the C builtin functions (which aren't descriptors) would be
a bit harder, but not much so:
from functools import partial
class Heap(list):
def __init__(self, iterable=None):
if iterable:
super().__init__(iterable)
else:
super().__init__()
self.heapify = partial(heapq.heapify, self)
self.push = partial(heapq.heappush, self)
...
self.heapify()
Thoughts?
>
> > To show this on simple example:
> >
> > >>> from itertools import count, islice
> > >>> it = count()
> > >>> x, y = it
> > >>> it
> > count(3)
>
> For everyone else who was confused by this, as I was, that's not
> actually a copy and paste from the REPL. There should be a ValueError
> raised after the x, y assignment. As given, it is confusing because it
> looks like the assignment succeeded, when in fact it didn't.
>
>
> > Here the count was advanced two times but assignment did not happen.
>
> Correct, because there was an exception raised.
>
Sorry for that, I did not want to embarrass anyone, so I wrote below that
the assignment did not happen. But probably the code should speak for
itself, especially if it looks like a copy from REPL
> if isinstance(it, collections.abc.Iterator):
> # special case for iterators
> x, y = it
> else:
> # sequences keep the old behaviour
> x, y = it[:2]
>
No, it can be simply x, y = iter(it)
> > Cons:
> > 1. A special case of how assignment works
> > 2. As with any implicit behavior, hard-to-find bugs
>
> Right. Hard-to-find bugs beats any amount of convenience in the
> interactive interpreter. To use an analogy:
>
> "Sure, sometimes my car suddenly shifts into reverse while I'm driving
> at 60 kph, sometimes the engine falls out when I go around the corner,
> and occasionally the brakes catch fire, but gosh the cup holder makes it
> really convenient to drink coffee while I'm stopped at traffic lights!"
>
:-)
Perhaps a better idea might be special syntax to tell the interpreter
> you don't want to run the right-hand side to completion. "Explicit is
> better than implicit" -- maybe something special like:
>
> x, y, * = iterable
>
I wrote somewhere above, that "may be I like this form". But for me *
'"starred" target implies -> collect something from iterable. So now I'm
towards:
x, y, ... = iterable
But I have not summed up yet what pitfalls can be on this path.
Thank you your remarks were very extensive!
With kind regards, -gdg
Python allows underscore character as a separator in variables.
This is better than nothing, still it does not make the look much better.
**Proposal**: allow additional separator, namely hyphen character.
**Benefits**: this should provide significant readability improvement.
Compared to most syntax change proposals that I remember till now,
this seems to have really tangible benefits. So all in all I see it as
a significant
language improvement.
Besides its direct benefit as a good looking separator, it also gives
an opprtunity
to reduce "camelCase" or similar ugly inclusions in code.
So one can easily compose human-readable variable names e.g.:
my-variable
figure-shape---width
etc.
**Problem**: currently hyphen character is used as a minus operator!
The problem is as old as the history of most programming languages,
and inherited from initial poorness of character sets.
Therefore I don't see a single optimal solution to this.
Possible solutions:
Solution 1:
Use another similar looking character from unicode,
for example: U+02D7 (modifier letter minus sign).
At the same time IMO it is needed to allow the minus character
for the minus operator, namely U+2212 Minus sign. This will
allow proper typography of source code.
Main benefit of such approach: no breakage of current code base,
since new chars are additional to existing ones.
Solution 2: (radical)
Disallow hyphen as minus operator, and use only U+2212 Minus sign.
I.e. "a-b" would be a variable and "a − b" a minus operation.
Advantage: opportunity to correct the improper character usage once and for all.
Disadvantage: breakage of current code base + force UTF-8 storage use (consider
e.g. editors without unicode support).
Thus most probably such solution will cause howl reaching to the sky among
users, despite many modern editors allow unicode and custom operator styling,
for example to distinguish dash from hyphen in a monospaced editor.
So is my proposal, and as usual urging for constructive conversation.
(i.e. proposing to write own language/translator is not constructive
conversation)
Cheers,
Mikhail
Following on from the discussions on pip I would like to suggest, (and
possibly implement), a minor change to the current py.exe python launcher.
Currently the launcher, when called without a version specifier,
defaults to the highest version on the basis of 3>2, x.11 > x.9, -64 >
-32 however this may not always be the most desirable behaviour.
I would like to suggest that it take a configuration value for the
default version to use, (and possibly a separate ones for pyw, & file
associations), honouring the following with the later overriding:
default - as current
system setting - from registry
user setting - from registry
user setting - from config file maybe %appdata%\pylauncher\defaults.ini
environment setting - from getenv
local setting - from .pyconfig file in the current directory.
Options would be the same format as the -X[.Y][-BB] format currently
accepted on the command line plus a --No-Py-Default option which would
always error out if the version to invoke was not specified.
I see this as potentially adding quite a lot of value for people with
multiple python versions installed and it could tie in quite well with
the possible use of py.exe as an entry point for tools such as pip.
It might also increase the awareness of the launcher as those who have
to stick with python 2 for the moment or in a specific context could set
the default to what they need but can always override.
--
Steve (Gadget) Barnes
Any opinions in this message are my personal opinions and do not reflect
those of my employer.
---
This email has been checked for viruses by AVG.
http://www.avg.com
Sorry. Unfortunately I had a mistake.
Alon Snir
Date: Thu, 23 Nov 2017 12:29:47 +1100
From: Steven D'Aprano <steve(a)pearwood.info>
To: python-ideas(a)python.org
Subject: Re: [Python-ideas] Rewriting the "roundrobin" recipe in the itertools documentation
Message-ID: <20171123012947.GT19802(a)ando.pearwood.info>
Content-Type: text/plain; charset=utf-8
On Wed, Nov 22, 2017 at 11:28:20AM +0000, Alon Snir wrote:
> It would be faster with ?deque?:
It isn't. According to my testing, your version with deque is
approximately two times slower than the version from toolz.itertoolz
that Wes quotes.
--
Steve
On Wed, Nov 22, 2017 at 10:52 PM, bunslow <bunslow(a)gmail.com> wrote:
> I'll just note the original proposal I made was specifically designed to
> be the minimum possible improvement, to avoid controversy (and e.g. a PEP).
>
> I agree that there are significant flaws and room for improvement in the
> current heapq module (which is why things like xheap exist), but even so
> it's still very useful as is, and the minimal OOP wrapper would go a long
> way towards usability of the current functionality (and of course "just use
> pip" is often not a viable course of action for certain developers). It
> seems that such a wrapper is widely (though not unanimously) approved.
>
> Next step I suppose is creating a bpo issue?
>
> On Wed, Nov 22, 2017 at 10:05 PM, Nick Coghlan <ncoghlan(a)gmail.com> wrote:
>
>> On 22 November 2017 at 11:00, Chris Angelico <rosuav(a)gmail.com> wrote:
>>
>>> So the question is more: why, with Python being the way it is, do the
>>> heap functions operate on a list? I think heapq.heapify is the answer:
>>> in linear time, it heapifies a list *in place*.
>>>
>>> I don't think there's any reason to have *both* interfaces to the heap
>>> functionality, but it certainly isn't illogical to try to treat a heap
>>> as a thing, and therefore have a Heap type.
>>>
>>
>> Right, the parallel here is that we have a "heapq" module for the same
>> reason that we have list.sort(), sorted(), and the bisect module, rather
>> than a single "SortedList" type. https://code.activestate.com/r
>> ecipes/577197-sortedcollection/ then provides an example of how to
>> combine those into a "SortedCollection" type.
>>
>> That said, I'm still in favour of adding an object-oriented wrapper to
>> either `collections` or the `heapq` module for all the classic OO reasons:
>>
>> - it makes it easier to reliably maintain the heap invariant (just drop
>> your list reference after passing it to the heap wrapper)
>> - it gives both human readers and static code analysers more information
>> to work with ("this is a heap" rather than "this is a list")
>> - it provides a hook for improved interactive help on heap instances
>>
>> I don't have any great concerns about potential confusion - the OO
>> wrapper will be easy enough to use that anyone that's unsure will likely
>> gravitate towards that, while the lower level `heapq` functions will remain
>> available for folks writing their own heap implementations.
>>
>> This effect would likely be even more pronounced if the OO wrapper were
>> made available as `collections.Heap` (`collections` already imports the
>> `heapq` module for use in the Counter implementation).
>>
>> Cheers,
>> Nick.
>>
>> --
>> Nick Coghlan | ncoghlan(a)gmail.com | Brisbane, Australia
>>
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas(a)python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
>
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
nexts = [ iter(it).__next__ for it in iterables ]
i = 0
while nexts:
i %= len(nexts)
try:
yield nexts[i]()
except StopIteration:
del nexts[i]
else:
i += 1
Regards
Alon Snir