Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Rob Cliffe via Python-Dev

On 03/07/2018 06:47, Tim Peters wrote:

[Rob Cliffe]
> It's late to raise this,

By months, yes ;-)

> but what exactly are the objections to the syntax
>         expr -> name  # or variations such as  expr => name
> instead of
>         name := expr

>
> The PEP mentions that this syntax does not have a problem that "as"
> does, but does not list any downsides of it.

My guess:  it probably strikes too many as "excessive novelty",  
 These are assignment expressions.  Python's assignment statements put 
the target at the left.  Why change that?  ":=" is used for assignment 
in many more other languages than "->" is.  Why fight that?


> It conforms to left-to-right evaluation, where name:=expr does not.

?  Only "expr" is evaluated, so left-to-right seems irrelevant here.  
The "evaluation" of a simple name as a binding target is a no-op (no 
code is generated).  If you really do see this as a wart anyway, then 
it's positively a Good Thing that it's exactly the same "wart" as in 
Python's assignment statements.


> It (I would argue) reduces the asymmetry of the first use of a
> sub-expression in cases such as
>     [ ( (f(x) -> y)**2, y**3, y**4) for x in iterable ]
>  vs
>     [ ( (y := f(x))**2, y**3, y**4) for x in iterable ]
> because the first "y" is closer to the way it is used, viz "**2".

The first form reads a little better to me too, but not a lot better.  
The problem I have with variations of this example on its own (which 
comes up surprisingly often with minor changes) is that it's clearer 
spelled today via


    [(y**2, y**3, y**4) for y in map(f, iterable)]

Spelling that with either form of assignment expression reads 
significantly worse than that to my eyes


But more importantly, it's expected that assignment expressions will 
be used _most_ often to make some common `if` and `while` patterns 
briefer.  Hardly all. Our eyes are already trained to "look at the far 
right end" for the value being tested, and, e.g.,


    while data := sock.recv():

preserves that.  Especially in code that doesn't _always_ use 
assignment expressions in such contexts (which is likely all 
significant blobs of code), it would be visually jarring to have to 
"sometimes look in the middle instead" to extract the important part of:


    while sockrecv() -> data:

"Look to the left for the name, look to the right for the value" is 
the rule for assignment statements, assignment expressions, and `for` 
loop targets.


But there's no "QED" here because this isn't a deductive science.  The 
final answer is "because that's what Guido liked best" ;-)

Thanks, Tim, for a thoughtful answer.
Don't get me wrong, I feel quite happy with ":=".  Perhaps you have 
managed to articulate some thoughts that were buried in my 
subconscious.  It's just that I couldn't come up with any rational 
objections to "->".

Rob Cliffe



 
	Virus-free. www.avg.com 
 



<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Comparing PEP 576 and PEP 580

2018-07-03 Thread Jeroen Demeyer

Hello all,

in order to make reviewing PEP 576/580 easier and possibly take some 
ideas from one PEP to the other, let me state the one fundamental 
difference between these PEPs. There are many details in both PEPs that 
can still change, so I'm focusing on what I think is the big structural 
difference.


To be clear: I'm referring to the PEP 576 version at
https://github.com/markshannon/pep-576/blob/master/README.rst
(this really should be merged in the main PEP repo).

Both PEPs add a hook for fast calling of C functions. However, they do 
that on a different level. Let's trace what _PyObject_FastCallKeywords() 
currently does when acting on an instance of builtin_function_or_method:


A. _PyObject_FastCallKeywords()
 calls
B. _PyCFunction_FastCallKeywords()
 which calls
C. _PyMethodDef_RawFastCallKeywords()
 which calls
D. the actual C function (*ml_meth)()

PEP 576 hooks the call A->B while PEP 580 hooks the call B->D (getting 
rid of C).


Advantages of the high-level hook (PEP 576):
* Much simpler protocol than PEP 580.
* More general since B can be anything.
* Not being forced to deal with "self".
* Slightly faster when you don't care about B.

Advantages of the low-level hook (PEP 580):
* No need to duplicate the code from B (see the various existing 
_{FOO}_FastCallKeywords functions).
* Enables certain optimizations because other code can make assumptions 
about what B does.


In my personal opinion, the last advantage of PEP 580 is really 
important: some existing optimizations depend on it and it also allows 
extending the protocol in a "performance-compatible" way: it's easy to 
extend the protocol in a way that callers can benefit from it.


Anyway, it would be good to have some guidance on how to proceed here. I 
would really like something like PEP 580 to be accepted and I'm willing 
to put time and effort into achieving that.



Thanks,
Jeroen.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Chris Barker via Python-Dev
On Mon, Jul 2, 2018 at 11:42 PM, Tim Peters  wrote:


> "comprehensions" was always a dubious term, carried over from set theory
> where the term focuses on the optional "if" part rather than the more
> fundamental iterator or computation parts.
>

I always wondered about that :-) -- I'd say for most of us that aren't
familiar with set theory, it's kind of a "sounds something like putting
thing together" word and I just left it at that, and learned what they are.


> So if we had it to do over again I'd sigh and accept "generator
> comprehensions" anyway.  It's been an eternal PITA - and especially in the
> PEP 572 threads! - to keep typing "comprehensions or generator
> expressions".
>

Well, too late to change the official name, but not too late to start using
the term in threads like these -- and other documentation, etc

I find there is a lot of confusion about the word "generator", as it
implies a "thing that generates values on the fly" (like, say the range()
object.

But then, in Python, a generator is something that gets crated by a
generator function, and CAN be an "thing (iterator) that generates things
on the fly", but can also be a more generic coroutine, and can be used in
nifty ways that really have nothing to do with generating a bunch of value.
(like pytest fixtures, for example)

So we have generators, iterators, and iterables, and generators can be
iterators, but aren't always, and any number of iterators can generate
values on the fly, and 

so it's all a bit of a mess to explain to a newbie.

Then again, if I had the power of Guido's time machine, I'd go back more,
> and not use "comprehensions" for anything to begin with.  Instead we'd have
> list, dict, set, and generator twizzlers, affectionately called listwiz,
> dictwiz, setwiz, and gentwiz by the cool kids :-)
>

I'd like that!

-CHB




-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Examples for PEP 572

2018-07-03 Thread Serhiy Storchaka
I like programming languages in which all are expressions (including 
function declarations, branching and loops) and you can use an 
assignment at any point, but Python is built on other ways, and I like 
Python too. PEP 572 looks violating several Python design principles. 
Python looks simple language, and this is its strong side. I believe 
most Python users are not professional programmers -- they are 
sysadmins, scientists, hobbyists and kids -- but Python is suitable for 
them because its clear syntax and encouraging good style of programming. 
In particularly mutating and non-mutating operations are separated. The 
assignment expression breaks this. There should be very good reasons for 
doing this. But it looks to me that all examples for PEP 572 can be 
written better without using the walrus operator.



results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]


results = [(x, y, x/y) for x in input_data for y in [f(x)] if y > 0]


stuff = [[y := f(x), x/y] for x in range(5)]


stuff = [[y, x/y] for x in range(5) for y in [f(x)]]

This idiom looks unusual for you? But this is a legal Python syntax, and 
it is not more unusual than the new walrus operator. This idiom is not 
commonly used because there is very little need of using above examples 
in real code. And I'm sure that the walrus operator in comprehension 
will be very rare unless PEP 572 will encourage writing complicated 
comprehensions. Most users prefer to write an explicit loop.


I want to remember that PEP 572 started from the discussion on 
Python-ideas which proposed a syntax for writing the following code as a 
comprehension:


smooth_signal = []
average = initial_value
for xt in signal:
average = (1-decay)*average + decay*xt
smooth_signal.append(average)

Using the "for in []" idiom this can be written (if you prefer 
comprehensions) as:


smooth_signal = [average
 for average in [initial_value]
 for x in signal
 for average in [(1-decay)*average + decay*x]]

Try now to write this using PEP 572. The walrus operator turned to be 
less suitable for solving the original problem because it doesn't help 
to initialize the initial value.



Examples from PEP 572:


# Loop-and-a-half
while (command := input("> ")) != "quit":
print("You entered:", command)


The straightforward way:

while True:
command = input("> ")
if command == "quit": break
print("You entered:", command)

The clever way:

for command in iter(lambda: input("> "), "quit"):
print("You entered:", command)


# Capturing regular expression match objects
# See, for instance, Lib/pydoc.py, which uses a multiline spelling
# of this effect
if match := re.search(pat, text):
print("Found:", match.group(0))
# The same syntax chains nicely into 'elif' statements, unlike the
# equivalent using assignment statements.
elif match := re.search(otherpat, text):
print("Alternate found:", match.group(0))
elif match := re.search(third, text):
print("Fallback found:", match.group(0))


It may be more efficient to use a single regular expression which 
consists of multiple or-ed patterns marked as different groups. For 
example see the cute regex-based tokenizer in gettext.py:



_token_pattern = re.compile(r"""
(?P[ \t]+)| # spaces and horizontal 
tabs
(?P[0-9]+\b)   | # decimal integer
(?Pn\b)  | # only n is allowed
(?P[()])  |
(?P[-*/%+?:]|[>,
 # <=, >=, ==, !=, &&, ||,
 # ? :
 # unary and bitwise ops
 # not allowed
(?P\w+|.)   # invalid token
""", re.VERBOSE|re.DOTALL)

def _tokenize(plural):
for mo in re.finditer(_token_pattern, plural):
kind = mo.lastgroup
if kind == 'WHITESPACES':
continue
value = mo.group(kind)
if kind == 'INVALID':
raise ValueError('invalid token in plural form: %s' % value)
yield value
yield ''


I have not found any code similar to the PEP 572 example in pydoc.py. It 
has different code:



pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
r'RFC[- ]?(\d+)|'
r'PEP[- ]?(\d+)|'
r'(self\.)?(\w+))')

...

start, end = match.span()
results.append(escape(text[here:start]))

all, scheme, rfc, pep, selfdot, name = match.groups()
if scheme:
url = escape(all).replace('"', '"')
results.append('%s' % (url, url))
elif rfc:
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
results.append('%s' % (url, escape(all)))
elif pep:

...

It doesn't look as a sequence of re.search() calls. It is

Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Chris Angelico
On Wed, Jul 4, 2018 at 7:37 AM, Serhiy Storchaka  wrote:
> I believe most Python users are not
> professional programmers -- they are sysadmins, scientists, hobbyists and
> kids --

[citation needed]

> In particularly mutating and
> non-mutating operations are separated. The assignment expression breaks
> this.

[citation needed]

In terms of blending mutating and non-mutating operations, augmented
assignment is far worse. Contrast:

>>> x = 1
>>> y = x
>>> x += 1

>>> a = [1]
>>> b = a
>>> a += [2]


Assignment expressions do the exact same thing as assignment
statements, but also allow you to keep using that value. There is
nothing about mutation. (Unless you believe that assignment *itself*
is mutation, in which case Python is definitely the wrong language for
you.)

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Terry Reedy

On 7/3/2018 2:42 AM, Tim Peters wrote:

So if we had it to do over again I'd sigh and accept "generator 
comprehensions" anyway.  It's been an eternal PITA - and especially in 
the PEP 572 threads! - to keep typing "comprehensions or generator 
expressions".  Then again, if I had the power of Guido's time machine, 
I'd go back more, and not use "comprehensions" for anything to begin 
with.


Amen.  I cannot make 'comprehension' in this context comprehensible 
without some linguistic twisting.


  Instead we'd have list, dict, set, and generator twizzlers, 
affectionately called listwiz, dictwiz, setwiz, and gentwiz by the cool 
kids :-)


I learned the set notion, such as
{n^2: n in  N; 1 <= n < 100, n even}  # math
{n*n for n in range(1,100) if not n%2}  # python
as 'set builder' notation.

If we had followed the math precedent, instead of language>, we would have set builders, list builders, dict builders, and 
generator builders.


I half seriously think we should consider this for 3.8 for the benefit 
of future Python programmers as well as ourselves.  Comprehensions that 
can contain assignment expressions are a slightly new thing.



--
Terry Jan Reedy


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Guido van Rossum
I smell a new thread. :-)

On Tue, Jul 3, 2018 at 3:06 PM Terry Reedy  wrote:

> On 7/3/2018 2:42 AM, Tim Peters wrote:
>
> > So if we had it to do over again I'd sigh and accept "generator
> > comprehensions" anyway.  It's been an eternal PITA - and especially in
> > the PEP 572 threads! - to keep typing "comprehensions or generator
> > expressions".  Then again, if I had the power of Guido's time machine,
> > I'd go back more, and not use "comprehensions" for anything to begin
> > with.
>
> Amen.  I cannot make 'comprehension' in this context comprehensible
> without some linguistic twisting.
>
> >  Instead we'd have list, dict, set, and generator twizzlers,
> > affectionately called listwiz, dictwiz, setwiz, and gentwiz by the cool
> > kids :-)
>
> I learned the set notion, such as
> {n^2: n in  N; 1 <= n < 100, n even}  # math
> {n*n for n in range(1,100) if not n%2}  # python
> as 'set builder' notation.
>
> If we had followed the math precedent, instead of  language>, we would have set builders, list builders, dict builders, and
> generator builders.
>
> I half seriously think we should consider this for 3.8 for the benefit
> of future Python programmers as well as ourselves.  Comprehensions that
> can contain assignment expressions are a slightly new thing.
>
>
> --
> Terry Jan Reedy
>
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>


-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Chris Barker via Python-Dev
On Tue, Jul 3, 2018 at 2:51 PM, Chris Angelico  wrote:

> On Wed, Jul 4, 2018 at 7:37 AM, Serhiy Storchaka 
> wrote:
> > I believe most Python users are not
> > professional programmers -- they are sysadmins, scientists, hobbyists and
> > kids --
>
> [citation needed]


fair enough, but I think we all agree that *many*, if not most, Python
users are "not professional programmers". While on the other hand everyone
involved in discussion on python-dev and python-ideas is a serious (If not
"professional") programmer.

So we do have a bit of a disconnect between much of the user base and folks
making decisions about how the language evolves -- which is probably
inevitable,

Over the years I've been using it (most of its life), Python has evolved to
become much less of a "scripting" language, and much more of a "systems"
language, and this addition is a (pretty significant) step more in that
direction.

Serhiy: FWIW, a number of us made the case about the additional complexity
of this feature in this discussion -- I think it was a bit side-tracked by
the impression that we were only talking about newbies (and also by scope
of comprehensions), but the point was made and I assume considered.


> > In particularly mutating and
> > non-mutating operations are separated. The assignment expression breaks
> > this.
>

I'd call it "local namespace manipulating and non-local namespace
manipulating", but yes, that is my concern as well.

In terms of blending mutating and non-mutating operations, augmented
> assignment is far worse.


yeah -- I've always thought it was a shame that augmented assignment worked
on immutables :-(

-CHB



-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Greg Ewing

Terry Reedy wrote:
If we had followed the math precedent, instead of language>, we would have set builders, list builders, dict builders, and 
generator builders.


I was intending to suggest something like that back when
comprehensions were first being discussed, but people
raced ahead and adopted the term "comprehension" before
I got the chance.

"List builder" and "dict builder" make a lot of sense,
but "generator builder" not so much -- it *is* a generator,
not something that builds a generator. In fact it doesn't
build anything in the sense that the others do. So maybe
"generator expression" is the best we could have done.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Victor Stinner
2018-07-02 20:19 GMT+02:00 Guido van Rossum :
> Thank you all. I will accept the PEP as is. (...)

I see more and more articles ("on the Internet") saying that Guido van
Rossum already accepted the PEP. Is the PEP already accepted or will
be accepted?

Right now, https://www.python.org/dev/peps/pep-0572/ status is "Draft".

Victor
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)

2018-07-03 Thread Guido van Rossum
On Tue, Jul 3, 2018 at 4:25 PM Victor Stinner  wrote:

> 2018-07-02 20:19 GMT+02:00 Guido van Rossum :
> > Thank you all. I will accept the PEP as is. (...)
>
> I see more and more articles ("on the Internet") saying that Guido van
> Rossum already accepted the PEP. Is the PEP already accepted or will
> be accepted?
>
> Right now, https://www.python.org/dev/peps/pep-0572/ status is "Draft".
>

That's a rather philosophical question. I clearly said "I will" not "I
might". And if you're asking whether it's likely that I'll change my mind,
no. I would like help with updates to the PEP to summarize some of the
discussions and rejected proposals. And I am giving myself a week to "cool
off". But I am muting threads that bring up objections that I've heard
before (e.g. "design principles"). So those articles aren't wrong. Your
patience is appreciated.

-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Naming comprehension syntax [was Re: Informal educator feedback on PEP 572 ...]

2018-07-03 Thread Steven D'Aprano
On Wed, Jul 04, 2018 at 11:13:20AM +1200, Greg Ewing wrote:
> Terry Reedy wrote:
> >If we had followed the math precedent, instead of  >language>, we would have set builders, list builders, dict builders, and 
> >generator builders.
> 
> I was intending to suggest something like that back when
> comprehensions were first being discussed, but people
> raced ahead and adopted the term "comprehension" before
> I got the chance.
> 
> "List builder" and "dict builder" make a lot of sense,
> but "generator builder" not so much -- it *is* a generator,
> not something that builds a generator. In fact it doesn't
> build anything in the sense that the others do. So maybe
> "generator expression" is the best we could have done.

But [expr for x in seq] is a list, just as (expr for ...) is a 
generator. If you don't believe me, try it:

py> type([x for x in (1,)])


py> type(x for x in (1,))


So I think the similarity is complete. Further, if we think of "list 
builder" as an abbreviation of "list builder syntax", we have:

- list builder syntax is syntax which returns a list;

- dict builder syntax is syntax which returns a dict;

- set builder syntax is syntax which returns a set;

- generator builder syntax is syntax which returns a generator.


Of course, there are other ways to build lists, such as calling the 
constructor, or using a list display ("list literal", except it isn't 
always a literal). But they're not *builder syntax* :-)

In hindsight, I think "spam builder (syntax)" would have been better 
than the rather mysterious technical word "comprehension" and the not 
very felicitous term "generator expression".


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread INADA Naoki
​

> > In particularly mutating and
> > non-mutating operations are separated. The assignment expression breaks
> > this.
>
> [citation needed]
>
> In terms of blending mutating and non-mutating operations, augmented
> assignment is far worse. Contrast:
>
> >>> x = 1
> >>> y = x
> >>> x += 1
>
> >>> a = [1]
> >>> b = a
> >>> a += [2]
>
>
> Assignment expressions do the exact same thing as assignment
> statements, but also allow you to keep using that value. There is
> nothing about mutation. (Unless you believe that assignment *itself*
> is mutation, in which case Python is definitely the wrong language for
> you.)
>
>
​I think Serhiy use "mutation" as "assignment", or "changing variable".​
​And at this point, I'm with Serhiy.​

Before PEP 572, assignment is happened on very limited places.
When we want to use "variable x", we can check "x isn't changed from
value I want" very quickly, without reading full code.  For example,

  with open(some_file) as f:
  for line in f:
  line = line.rstrip()
  # some code here
  self.some_method(..., # some long arguments
   (line := line.split())[0], line[1], # oops!
   ...)
  # some code here
  x = {k: f for k in line if (f := k.upper()).startswith('F')} #
oops!
  # some code here

Before PEP 572, we can check "f is not changed from `as f`" and "line
is not changed from `line = line.rstrip()`" very quickly, without
reading expressions in argument list or comprehension.

After PEP 572, we need to read all code between place we want to use
some variable and these variables are assigned to expected value.

In this meaning, ​augmented assignment is far better than assignment
expression.
It's very easy to find, same to "as x" or "x =".

​So PEP 572 will reduce maintainability of code written
​by ​
others
​ (1)


(1) "others" including "I" in several months ago.


Linters helps us sometime, but linter can't help us when others who written
the code​ didn't
use linter and it's difficult to solve every warning from linters.

​This is what I feel how PEP 572 is different from f-string or ternary
expression.
f-string and ternary expression can do only what expressions can.
But PEP 572 expands "what expressions can".

I feel PEP 572 breaks border between expression and statement, and it makes
readability of dirty code worse.

On the other hand, I understand PEP 572 allows clever code simplifies
tedious
code.  It may increase readability of non-dirty code.

Regards,

-- 
INADA Naoki  
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Tim Peters
[INADA Naoki]
> ...
> On the other hand, I understand PEP 572 allows clever code
> simplifies tedious code.  It may increase readability of non-dirty code.

The latter is the entire intent ,of course.  We can't force people to write
readable code, but I don't understand the widespread assumption that other
programmers are our enemies who have to be preemptively disarmed ;-)

Use code review to enforce readable code.  If you want a coding standard
here, use mine:  "if using an assignment expression isn't obviously better
(at least a little so), DON'T USE IT".  That's the same standard I use for
lots of things (e.g., is such-&-such better as a listcomp or as nested
loops?).  It only requires that you have excellent taste in what "better"
means ;-)

As I noted in the PEP's Appendix A, I refuse to even write code like

i = j = count = nerrors = 0

because it squashes conceptually distinct things into a single statement .
I'll always write that as

i = j = 0
count = 0
nerrors = 0

instead - or even in 4 lines if `i` and `j` aren't conceptually related.

That's how annoyingly pedantic I can be ;-)   Yet after staring at lots of
code, starting from a neutral position (why have an opinion about anything
before examination?), I became a True Believer.

I really don't know what Guido likes best about this, but for me it's the
large number of objectively small wins in `if` and `while` contexts.   They
add up.  That conclusion surprised me.  That there are occasionally bigger
wins to be had is pure gravy.

But in no case did I count "allows greater cleverness" as a win.  The
Appendix contains a few examples of "bad" uses too, where cleverness in
pursuit of brevity harms clarity.  In fact, to this day, I believe those
examples derived from abusing assignment expressions in real-life code are
more horrifying than any of the examples anyone else _contrived_ to "prove"
how bad the feature is.

I apparently have more faith that people will use the feature as intended.
Not all people, just most.  The ones who don't can be beaten into
compliance, same as with any other abused feature ;-)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Comparing PEP 576 and PEP 580

2018-07-03 Thread INADA Naoki
I think both PEPs are relying on FASTCALL calling convention,
and can't be accepted until FASTCALL is stable & public.

There are enough time before Python 3.8 is released.
Let's go step by step.

Regards,

On Wed, Jul 4, 2018 at 12:10 AM Jeroen Demeyer  wrote:

> Hello all,
>
> in order to make reviewing PEP 576/580 easier and possibly take some
> ideas from one PEP to the other, let me state the one fundamental
> difference between these PEPs. There are many details in both PEPs that
> can still change, so I'm focusing on what I think is the big structural
> difference.
>
> To be clear: I'm referring to the PEP 576 version at
> https://github.com/markshannon/pep-576/blob/master/README.rst
> (this really should be merged in the main PEP repo).
>
> Both PEPs add a hook for fast calling of C functions. However, they do
> that on a different level. Let's trace what _PyObject_FastCallKeywords()
> currently does when acting on an instance of builtin_function_or_method:
>
> A. _PyObject_FastCallKeywords()
>   calls
> B. _PyCFunction_FastCallKeywords()
>   which calls
> C. _PyMethodDef_RawFastCallKeywords()
>   which calls
> D. the actual C function (*ml_meth)()
>
> PEP 576 hooks the call A->B while PEP 580 hooks the call B->D (getting
> rid of C).
>
> Advantages of the high-level hook (PEP 576):
> * Much simpler protocol than PEP 580.
> * More general since B can be anything.
> * Not being forced to deal with "self".
> * Slightly faster when you don't care about B.
>
> Advantages of the low-level hook (PEP 580):
> * No need to duplicate the code from B (see the various existing
> _{FOO}_FastCallKeywords functions).
> * Enables certain optimizations because other code can make assumptions
> about what B does.
>
> In my personal opinion, the last advantage of PEP 580 is really
> important: some existing optimizations depend on it and it also allows
> extending the protocol in a "performance-compatible" way: it's easy to
> extend the protocol in a way that callers can benefit from it.
>
> Anyway, it would be good to have some guidance on how to proceed here. I
> would really like something like PEP 580 to be accepted and I'm willing
> to put time and effort into achieving that.
>
>
> Thanks,
> Jeroen.
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/songofacandy%40gmail.com
>


-- 
INADA Naoki  
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Terry Reedy

On 7/3/2018 5:37 PM, Serhiy Storchaka wrote:
I like programming languages in which all are expressions (including 
function declarations, branching and loops) and you can use an 
assignment at any point, but Python is built on other ways, and I like 
Python too. PEP 572 looks violating several Python design principles. 
Python looks simple language, and this is its strong side. I believe 
most Python users are not professional programmers -- they are 
sysadmins, scientists, hobbyists and kids -- but Python is suitable for 
them because its clear syntax and encouraging good style of programming. 
In particularly mutating and non-mutating operations are separated. The 
assignment expression breaks this. There should be very good reasons for 
doing this. But it looks to me that all examples for PEP 572 can be 
written better without using the walrus operator.
I appreciate you showing alternatives I can use now.  Even once 
implemented, one can not use A.E's until one no longer cares about 3.7 
compatibility.  Then there will still be a choice.



results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]


     results = [(x, y, x/y) for x in input_data for y in [f(x)] if y > 0]


Would (f(x),) be faster?

import timeit as ti

print(ti.timeit('for y in {x}: pass', 'x=1'))
print(ti.timeit('for y in [x]: pass', 'x=1'))
print(ti.timeit('for y in (x,): pass', 'x=1'))

# prints
0.1376525449996  # seconds per 1_000_000 = microseconds each.
0.103212743
0.0949247330004

Yes, but not enough to pay for adding ',', and sometimes forgetting.


stuff = [[y := f(x), x/y] for x in range(5)]

 stuff = [[y, x/y] for x in range(5) for y in [f(x)]]


Creating an leaky name binding appears to about 5 x faster than 
iterating a temporary singleton.


print(ti.timeit('y=x', 'x=1'))
print(ti.timeit('y=x; del y', 'x=1'))
#
0.01735777899907
0.02111505100107

If one adds 'del y' to make the two equivalent, the chars typed is about 
the same.  To me, the choice amounts to subject reference.  Even with 
y:=x available, I would write the expansion as


res = []
for x in range(5):
y = f(x)
res.append((y, x/y))

rather than use the assignment expression in the tuple.  It creates a 
'hitch' in thought.


This idiom looks unusual for you? But this is a legal Python syntax, and 
it is not more unusual than the new walrus operator. This idiom is not 
commonly used because there is very little need of using above examples 
in real code. And I'm sure that the walrus operator in comprehension 
will be very rare unless PEP 572 will encourage writing complicated 
comprehensions. Most users prefer to write an explicit loop.


I want to remember that PEP 572 started from the discussion on 
Python-ideas which proposed a syntax for writing the following code as a 
comprehension:


     smooth_signal = []
     average = initial_value
     for xt in signal:
     average = (1-decay)*average + decay*xt
     smooth_signal.append(average)

Using the "for in []" idiom this can be written (if you prefer 
comprehensions) as:


     smooth_signal = [average
  for average in [initial_value]
  for x in signal
  for average in [(1-decay)*average + decay*x]]

Try now to write this using PEP 572. The walrus operator turned to be 
less suitable for solving the original problem because it doesn't help 
to initialize the initial value.



Examples from PEP 572:


# Loop-and-a-half
while (command := input("> ")) != "quit":
    print("You entered:", command)


The straightforward way:

     while True:
     command = input("> ")
     if command == "quit": break
     print("You entered:", command)

The clever way:

     for command in iter(lambda: input("> "), "quit"):
     print("You entered:", command)


The 2-argument form of iter is under-remembered and under-used.  The 
length difference is 8.

while (command := input("> ")) != "quit":
for command in iter(lambda: input("> "), "quit"):

I like the iter version, but the for-loop machinery and extra function 
call makes a minimal loop half a millisecond slower.


import timeit as ti

def s():
it = iter(1*'0' + '1')

def w():
it = iter(1*'0' + '1')
while True:
command = next(it)
if command == '1': break

def f():
it = iter(1*'0' + '1')
for command in iter(lambda: next(it), '1'): pass

print(ti.timeit('s()', 'from __main__ import s', number=1000))
print(ti.timeit('w()', 'from __main__ import w', number=1000))
print(ti.timeit('f()', 'from __main__ import f', number=1000))
#
0.00097021275
0.936525425001
1.591311794998

Of course, with added processing of 'command' the time difference 
disappears.  Printing (in IDLE) is an extreme case.


def wp():
it = iter(100*'0' + '1')
while True:
command = next(it)
if command == '1': break
print('w', command)

def fp():
it = iter(100*'0' + '1')
for command in

Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Steven D'Aprano
On Tue, Jul 03, 2018 at 09:54:22PM -0400, Terry Reedy wrote:


> >     results = [(x, y, x/y) for x in input_data for y in [f(x)] if y > 0]
> 
> Would (f(x),) be faster?

There is a deferred feature request to optimize "for x in [item]" as 
equivalent to "for x in (item,)", to avoid constructing a list:

https://bugs.python.org/issue32856

Since it only affects the internal byte-code, not visible semantics 
(aside from speed and memory) I think that's a neat micro-optimization 
regardless of whether it is applied to comprehensions or regular 
for-loops or both.




-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Serhiy Storchaka

04.07.18 00:51, Chris Angelico пише:

On Wed, Jul 4, 2018 at 7:37 AM, Serhiy Storchaka  wrote:

I believe most Python users are not
professional programmers -- they are sysadmins, scientists, hobbyists and
kids --


[citation needed]


I don't understand what citation do you need.


In particularly mutating and
non-mutating operations are separated. The assignment expression breaks
this.


[citation needed]


In Python the assignment (including the augmented assignment) is a 
statement, del is a statement, function and class declarations are 
statements, import is a statement. Mutating methods like list.sort() and 
dict.update() return None to discourage using them in expressions. This 
a common knowledge, I don't know who's citation you need.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Serhiy Storchaka

04.07.18 03:24, INADA Naoki пише:

I feel PEP 572 breaks border between expression and statement, and it makes
readability of dirty code worse.


Thank you, this is what I meant.

On the other hand, I understand PEP 572 allows clever code simplifies 
tedious

code.  It may increase readability of non-dirty code.


Unfortunately, I have not seen any example of this yet.

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Examples for PEP 572

2018-07-03 Thread Serhiy Storchaka

04.07.18 04:26, Tim Peters пише:
I really don't know what Guido likes best about this, but for me it's 
the large number of objectively small wins in `if` and `while` 
contexts.   They add up.  That conclusion surprised me.  That there are 
occasionally bigger wins to be had is pure gravy.


Could you please show me several examples in real code? I have not seen 
any win yet.


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Naming comprehension syntax [was Re: Informal educator feedback on PEP 572 ...]

2018-07-03 Thread Greg Ewing

Steven D'Aprano wrote:

- list builder syntax is syntax which returns a list;

- dict builder syntax is syntax which returns a dict;

- set builder syntax is syntax which returns a set;

- generator builder syntax is syntax which returns a generator.


You only get a list/dict/set from the first three after
you've run the iterators within it, but with a generator
expression, you already have a generator before you've
run it. That makes it feel different to me.

--
Greg
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com