Re: [Python-Dev] PEP 572: Assignment Expressions

2018-04-23 Thread Stephen J. Turnbull
Tim Peters writes:

 > Regardless, Guido has already said "as" is DOA (Dead On Arrival)
 > (illustrating that it's also common enough in English to give a short
 > name before its long-winded meaning ;-) ).

The parens above are a gloss on a well-known acronym for those who
have not encountered it before.  Neologisms are usually written in the
other order: "dead on arrival (DOA, for short)." ;-)

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Chris Jerdonek
On Mon, Apr 23, 2018 at 4:54 PM, Greg Ewing  wrote:
> Tim Peters wrote:
>
>> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
>> return g
>
>
> My problem with this is -- how do you read such code out loud?

It could be--

"if diff, which we let equal x - x_base, and g, which ..." or
"if diff, which we set equal to x - x_base, and g, which " or
"if diff, which we define to be x - x_base, and g, which " or
"if diff, which we define as x - x_base, and g, which ." etc.

--Chris



>
> From my Pascal days I'm used to reading ":=" as "becomes". So
> this says:
>
>"If diff becomes x - base and g becomes gcd(diff, n) is
> greater than or equal to 1 then return g."
>
> But "diff becomes x - base" is not what we're testing! That
> makes it sound like the result of x - base may or may not
> get assigned to diff, which is not what's happening at all.
>
> The "as" variant makes more sense when you read it as an
> English sentence:
>
>if ((x - x_base) as diff) and ...
>
>"If x - x_base (and by the way, I'm going to call that
> diff so I can refer to it later) is not zero ..."
>
> --
> 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/chris.jerdonek%40gmail.com
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Steven D'Aprano
On Mon, Apr 23, 2018 at 03:36:10PM -0700, Guido van Rossum wrote:
> Using 'as' was debated extensively on python-ideas. I don't like it for
> several reasons:
[...]

For what it is worth, I was one of the original proponents of the "as" 
syntax, but at this point I am no longer going to argue for it. I'm 
satisfied that using "as" has disadvantages, and that := is an 
acceptable alternative.

While I haven't changed my mind that putting the expression first and 
the target second is better, I'm satisfied that it is not so much better 
that it is worth extending this enormous discussion even further.

In other words, as far as I am concerned, I am happy to take the syntax 
as decided: "expr as name" is rejected and "name := expr" is acceptable.

I'm also satisfied that *at least for now* we should stick to only 
allowing simple names. We can always loosen the restriction later and 
allow arbitrarily complex targets at a later date, but we can't easily 
change our mind and prohibit them.



-- 
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] PEP 572: Assignment Expressions

2018-04-23 Thread Tim Peters
[Tim]
>> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
>> return g

[Greg Ewing ]
> My problem with this is -- how do you read such code out loud?

In the message in which I first gave that example:

if the diff isn't 0 and gcd(diff, n) > 1, return the gcd.
   That's how I _thought_ of it from the start.

In my mind, `x - x_base` doesn't even exist except as a low-level
definition of what "diff" means.  It's different for the other test:
_there_ `g` doesn't exist except as a shorthand for "the gcd".  In one
case it's the name that's important to me, and in the other case the
expression.  The entire function from which this came is doing all
arithmetic modulo `n`, so `n` isn't in my mind either - it's a
ubiquitous part of the background in this specific function.

But you did ask how_I_ would read that code ;-)  Anyone else is free
to read it however they like.  I naturally read it in the way that
makes most sense to me in its context.


> From my Pascal days I'm used to reading ":=" as "becomes". So
> this says:
>
>"If diff becomes x - base and g becomes gcd(diff, n) is
> greater than or equal to 1 then return g."
>
> But "diff becomes x - base" is not what we're testing!

I don't really follow that.  In Python,

if f() and g > 1:

first tests whether `f()` "is truthy", regardless of whether it does
or doesn't appear in a binding expression.  Because this code is
working with integers, there's an _implied_ "!= 0" comparison.


> That makes it sound like the result of x - base may or may not
> get assigned to diff, which is not what's happening at all.

Then I suggest the problem you're having doesn't stem from the binding
expression, but from that you're omitting to fill in the != 0 part:
if you're not thrown by "greater than 1", I can't see how you can be
thrown by "not zero".


> The "as" variant makes more sense when you read it as an
> English sentence:
>
>if ((x - x_base) as diff) and ...
>
>"If x - x_base (and by the way, I'm going to call that
> diff so I can refer to it later) is not zero ..."

So read the original as "if diff (which is x - x_base) is not zero ...".

Regardless, Guido has already said "as" is DOA (Dead On Arrival)
(illustrating that it's also common enough in English to give a short
name before its long-winded meaning ;-) ).
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Greg Ewing

Sven R. Kunze wrote:


if (x - x_base) and gcd(x - x_base, n) > 1:
return gcd(x - x_base, n)

and have the interpreter handle the optimization, or apply an lru_cache? ;-)


Problem is, there's no way to automatically tell whether
the expressions involved have side effects that are being
relied on.

--
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] PEP 572: Assignment Expressions

2018-04-23 Thread Greg Ewing

Tim Peters wrote:


if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
return g


My problem with this is -- how do you read such code out loud?

From my Pascal days I'm used to reading ":=" as "becomes". So
this says:

   "If diff becomes x - base and g becomes gcd(diff, n) is
greater than or equal to 1 then return g."

But "diff becomes x - base" is not what we're testing! That
makes it sound like the result of x - base may or may not
get assigned to diff, which is not what's happening at all.

The "as" variant makes more sense when you read it as an
English sentence:

   if ((x - x_base) as diff) and ...

   "If x - x_base (and by the way, I'm going to call that
diff so I can refer to it later) is not zero ..."

--
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] PEP 572: Assignment Expressions

2018-04-23 Thread Glenn Linderman

On 4/23/2018 1:01 PM, Ethan Furman wrote:

On 04/22/2018 10:44 PM, Tim Peters wrote:

[Guido]
In reality there often are other conditions being applied to the 
match for
which `if expr as name` is inadequate. The simplest would be 
something like


   if ...:
   
   elif (m := re.match('(.*):(.*)', line)) and m.group(1) == 
m.group(2):

 

And the match() call may not even be the first thing to check -- 
e.g. we

could have

 elif line is not None and (m := re.match('(.*):(.*)', line)) 
and m.group(1) == m.group(2):


I find myself warming more to binding expressions the more I keep them
in mind while writing new code.  And I think it may be helpful to
continue showing real examples where they would help.

Today's example:  I happened to code this a few hours ago:

diff = x - x_base
if diff:
 g = gcd(diff, n)
 if g > 1:
 return g

It's not really hard to follow, but two levels of nesting "feels
excessive", as does using the names "diff" and "g" three times each.
It's _really_ an "and" test:  if the diff isn't 0 and gcd(diff, n) >
1, return the gcd.  That's how I _thought_ of it from the start.

Which this alternative expresses directly:

if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
 return g


So I really like being able to make the assignment in the expression, 
but I have a really hard time parsing it with the name first.


Attempting to read just the names first:

  if
    diff
  scan for ending right paren
  found
  and
 g
  scan for ending right paren
    oops, found opening left paren
    scan for ending right paren
    found
  resume scanning for final right paren
  found
 > 1:
 return g


Attempting to read expressions first:

  if
    x - x_base
  and
    gcd(diff, n)
  what's diff?
    scan backwards
  diff is x - x_base
    > 1:
    return g
  what's g?
    scan up and backwards
    g is gcd(diff, n)


Attempting to read interleaved:

  if
    skip diff
  x - x_base
  back to diff
    as diff
  and
    skip g
  gcd(diff, n)
  back to g
    as g
  > 1:
  return g


On the other hand, if it were using the "as" keyword:

if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
    return g

I would parse as:

  if
    x - x_base
    as diff
  and
    gcd(diff, n)
    as g
  > 1:
  return g

For me at least, the last is much more readable.  Thinking about it 
some more, the problem (or maybe just my problem) is that I see an 
"if" or "while" and the I look for the thing that is True or False, 
and using the ":=" syntax the first thing I see is a placeholder for a 
result that doesn't exist yet, making me constantly scan backwards and 
forwards to put all the pieces in the correct place.


With "as", it just flows forwards.


You need to borrow the time machine, and get with those early 
mathematicians that first said:


Let x be the sum of y and z

and convince them that what they should have said was:

Let the sum of y and z be called x.

:)
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Matěj Cepl
On 2018-04-23, 21:34 GMT, Sven R. Kunze wrote:
> Is it just me or since when has the following Python code 
> fallen out of favor?

It isn’t just you.

Matěj
-- 
https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz
GPG Finger: 3C76 A027 CA45 AD70 98B5  BC1D 7920 5802 880B C9D8
 
… one of the main causes of the fall of the Roman Empire was
that, lacking zero, they had no way to indicate successful
termination of their C programs.  
  -- Robert Firth

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Guido van Rossum
Using 'as' was debated extensively on python-ideas. I don't like it for
several reasons:

- the semantics are subtly different from all other uses of 'as' in Python;
I'd like to reserve 'as' for "not a plain assignment"
- a short word is easier to miss when skimming code than punctuation
- most other languages (Java*, C*) borrow from assignment (name = expr)


On Mon, Apr 23, 2018 at 3:19 PM, Ned Deily  wrote:

> On Apr 23, 2018, at 18:04, Tim Peters  wrote:
> > However, against "as" is that its current use in "with" statements
> > does something quite different:
> >
> >with f() as name:
> >
> > does not bind the result of `f()` to `name`, but the result of
> > `f().__enter__()`.  Whether that "should be" fatal, I don't know, but
> > it's at least annoying ;-)
>
> Prior art: COBOL uses "GIVING", as in:
>
>ADD x, y GIVING z
>
> No need to re-invent the wheel ;)
>
> --
>   Ned Deily
>   n...@python.org -- []
>
> ___
> 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] PEP 572: Assignment Expressions

2018-04-23 Thread Paul G
On 04/23/2018 06:04 PM, Tim Peters wrote:

> However, against "as" is that its current use in "with" statements
> does something quite different:
> 
> with f() as name:
> 
> does not bind the result of `f()` to `name`, but the result of
> `f().__enter__()`.  Whether that "should be" fatal, I don't know, but
> it's at least annoying ;-)


This could be read a different way, though, since `with f()` calls 
`f().__enter__()`, you could read it as `(with f()) as name:`, in which case it 
does the same thing as an `as`-based binding expression would. Viewing it that 
way *also* helps alleviate the cognitive problem that `with f() as name` and 
`with (f() as name)` do two different things - the parentheses there are 
changing the precedence in the same way that `2 + 4 * 3` and `(2 + 4) * 3` do 
two different things.

This sorta also works for `except`, if you read it as `(except SomeException) 
as e:`, but I think this fiction falls apart when you look at `import`, since 
`import foo` *already* binds "foo" to a name, and `import foo as bar` not only 
binds `foo` to `bar`, but also *doesn't* bind `foo` to `foo`.



signature.asc
Description: OpenPGP digital signature
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Ned Deily
On Apr 23, 2018, at 18:04, Tim Peters  wrote:
> However, against "as" is that its current use in "with" statements
> does something quite different:
> 
>with f() as name:
> 
> does not bind the result of `f()` to `name`, but the result of
> `f().__enter__()`.  Whether that "should be" fatal, I don't know, but
> it's at least annoying ;-)

Prior art: COBOL uses "GIVING", as in:

   ADD x, y GIVING z

No need to re-invent the wheel ;)

--
  Ned Deily
  n...@python.org -- []

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Guido van Rossum
Whereas I find it a deal-breaker for 'as'.

On Mon, Apr 23, 2018 at 3:15 PM, Ethan Furman  wrote:

> On 04/23/2018 03:04 PM, Tim Peters wrote:
>
>> [Ethan Furman ]
>>
>>> So I really like being able to make the assignment in the expression,
>>> but I
>>> have a really hard time parsing it with the name first.
>>>
>>> ...
>>>
>>> On the other hand, if it were using the "as" keyword:
>>>
>>> if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
>>>  return g
>>>
>>> I would parse as:
>>>
>>>if
>>>  x - x_base
>>>  as diff
>>>and
>>>  gcd(diff, n)
>>>  as g
>>>> 1:
>>>return g
>>>
>>> For me at least, the last is much more readable.  Thinking about it some
>>> more, the problem (or maybe just my problem) is that I see an "if" or
>>> "while" and the I look for the thing that is True or False, and using the
>>> ":=" syntax the first thing I see is a placeholder for a result that
>>> doesn't
>>> exist yet, making me constantly scan backwards and forwards to put all
>>> the
>>> pieces in the correct place.
>>>
>>> With "as", it just flows forwards.
>>>
>>
>> I can read it fine either way, and don't much care.  A possible
>> advantage of an "as" operator is that its precedence could be set to
>> bind just a tad stronger than comparisons (which include "is" and "is
>> not" in Python), and then, e.g.,
>>
>>  if f() as result is not None:
>>  do something with result
>>
>> could work as intended.  So long as people can't get "assignment
>> _statements_" out of their heads,
>>
>>  if result := f() is not None:
>>
>> groups instead as
>>
>>  if result := (f() is not None):
>>
>> which would almost never be _intended_.  Maybe spelling it "as"
>> instead could break that.
>>
>> However, against "as" is that its current use in "with" statements
>> does something quite different:
>>
>>  with f() as name:
>>
>> does not bind the result of `f()` to `name`, but the result of
>> `f().__enter__()`.  Whether that "should be" fatal, I don't know, but
>> it's at least annoying ;-)
>>
>
> "as" does something slightly different in each of its current
> incantations, but the one thing that they all have in common is taking some
> thing on the left and giving it the name on the right:
>
> - imports -> thing on left gets name on right
> - exceptions -> exception that matches class on left gets name on right
> - with -> result of left.__enter__() gets name on right
>
> I see very little harm in adding
>
> - expression-binding -> eval(thing on left) gets name on right
>
> --
> ~Ethan~
>
>
> ___
> 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] PEP 572: Assignment Expressions

2018-04-23 Thread Ethan Furman

On 04/23/2018 03:04 PM, Tim Peters wrote:

[Ethan Furman ]

So I really like being able to make the assignment in the expression, but I
have a really hard time parsing it with the name first.

...

On the other hand, if it were using the "as" keyword:

if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
 return g

I would parse as:

   if
 x - x_base
 as diff
   and
 gcd(diff, n)
 as g
   > 1:
   return g

For me at least, the last is much more readable.  Thinking about it some
more, the problem (or maybe just my problem) is that I see an "if" or
"while" and the I look for the thing that is True or False, and using the
":=" syntax the first thing I see is a placeholder for a result that doesn't
exist yet, making me constantly scan backwards and forwards to put all the
pieces in the correct place.

With "as", it just flows forwards.


I can read it fine either way, and don't much care.  A possible
advantage of an "as" operator is that its precedence could be set to
bind just a tad stronger than comparisons (which include "is" and "is
not" in Python), and then, e.g.,

 if f() as result is not None:
 do something with result

could work as intended.  So long as people can't get "assignment
_statements_" out of their heads,

 if result := f() is not None:

groups instead as

 if result := (f() is not None):

which would almost never be _intended_.  Maybe spelling it "as"
instead could break that.

However, against "as" is that its current use in "with" statements
does something quite different:

 with f() as name:

does not bind the result of `f()` to `name`, but the result of
`f().__enter__()`.  Whether that "should be" fatal, I don't know, but
it's at least annoying ;-)


"as" does something slightly different in each of its current incantations, but the one thing that they all have in 
common is taking some thing on the left and giving it the name on the right:


- imports -> thing on left gets name on right
- exceptions -> exception that matches class on left gets name on right
- with -> result of left.__enter__() gets name on right

I see very little harm in adding

- expression-binding -> eval(thing on left) gets name on right

--
~Ethan~

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Tim Peters
[Ethan Furman ]
> So I really like being able to make the assignment in the expression, but I
> have a really hard time parsing it with the name first.
>
> ...
>
> On the other hand, if it were using the "as" keyword:
>
> if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
> return g
>
> I would parse as:
>
>   if
> x - x_base
> as diff
>   and
> gcd(diff, n)
> as g
>   > 1:
>   return g
>
> For me at least, the last is much more readable.  Thinking about it some
> more, the problem (or maybe just my problem) is that I see an "if" or
> "while" and the I look for the thing that is True or False, and using the
> ":=" syntax the first thing I see is a placeholder for a result that doesn't
> exist yet, making me constantly scan backwards and forwards to put all the
> pieces in the correct place.
>
> With "as", it just flows forwards.

I can read it fine either way, and don't much care.  A possible
advantage of an "as" operator is that its precedence could be set to
bind just a tad stronger than comparisons (which include "is" and "is
not" in Python), and then, e.g.,

if f() as result is not None:
do something with result

could work as intended.  So long as people can't get "assignment
_statements_" out of their heads,

if result := f() is not None:

groups instead as

if result := (f() is not None):

which would almost never be _intended_.  Maybe spelling it "as"
instead could break that.

However, against "as" is that its current use in "with" statements
does something quite different:

with f() as name:

does not bind the result of `f()` to `name`, but the result of
`f().__enter__()`.  Whether that "should be" fatal, I don't know, but
it's at least annoying ;-)
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Tim Peters
[Tim]
>> Surely you're joking.  This is math.gcd(), which is expensive for
>> multi-thousand bit integers, and the interpreter knows nothing about
>> it.  Adding a cache of _any_ kind (LRU or otherwise) would make it
>> even slower.

[Sven R. Kunze ]
> Alright, if that problem is just about performance,

It's not, but others had already pointed out that it's generally
considered Poor Practice (and for good reasons) to textually repeat
expressions, so I didn't echo that.  Even in purely functional
languages, where textually equal snippets are guaranteed to evaluate
to the same result every time, "give these expressions these brief
names" constructs are heavily used (see, .e.g, "let" and "where" in
Haskell).


>:then there must be a better way to resolve it rather than
> inventing a new syntax.

Why?  "Give the result of an expression a name" is already heavily
used in Python - it's just that the _contexts_ in which it can be done
are very limited now.


> Btw. storing the result in a local var is also a cache IMHO. And
> if gcd is immutable, I think Python can do a great job here of
> optimizing.

After decades, CPython still does nothing of the sort, short of having
eventually made, e.g., "None" and "True" and "False" reserved words so
at least it can optimize uses of those.  It knows nothing at all about
which library functions are pure - and there's no code in the
implementation currently capable of exploiting such information even
if it were known.  That remains a fantasy in CPython.


> Anyway, your example is the best one I've seen so far.

Guido gave better ones, where binding expressions would allow to
collapse arbitrarily deep levels of nesting to just one (if ... elif
... elif ... elif ...).  My example only eliminated a single level of
artificial indentation.  But my example did have the advantage of
being taken verbatim from actual, working code ;-)
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Sven R. Kunze

On 23.04.2018 23:19, Barry Warsaw wrote:

I also think it effectively solves the switch-statement problem:

if (get_response() as answer) == 'yes':
 do_it()
elif answer == 'no':
 skip_it()
elif answer == 'maybe'
 okay_then()

That’s Pythonic enough for jazz!


Is it just me or since when has the following Python code fallen out of 
favor?


answer = get_response()
if answer == 'yes':
do_it()
elif answer == 'no':
skip_it()
elif answer == 'maybe'
okay_then()

I really don't see anything I would want to optimize here. Not even a 
single bit. But as said that might just be me.


What I like about this code is:
1) symmetry: all ifs are equally structured
2) classic IPO model: first get input, then process (, then output)

Sven
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Chris Angelico
On Tue, Apr 24, 2018 at 7:25 AM, Sven R. Kunze  wrote:
> On 23.04.2018 22:37, Chris Angelico wrote:
>>
>> Ah, are you one of those programmers who writes code once and it's
>> instantly perfect? I apologize, I didn't realize I was in the presence
>> of a unicorn.
>
>
> Wow, constructive. Nothing is perfect, but if you don't consider your
> surroundings when doing changes, well, what could possibly go wrong...

I've seen way too many programmers - myself included - think that
synchronized edits are viable. If you are the one and only perfect
programmer, then sure! But if you're like the rest of us, it's better
to build your code in such a way that it doesn't bite you.

Yes, it was a snarky way to make the point, but I have a strong point to make.

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] PEP 572: Assignment Expressions

2018-04-23 Thread Sven R. Kunze

On 23.04.2018 22:37, Chris Angelico wrote:

Ah, are you one of those programmers who writes code once and it's
instantly perfect? I apologize, I didn't realize I was in the presence
of a unicorn.


Wow, constructive. Nothing is perfect, but if you don't consider your 
surroundings when doing changes, well, what could possibly go wrong...



Duplication works against that by forcing you to make changes in two places.


... in the very same line, a line below, few characters after/before it.


I've seen code that relies on duplication and compiler optimizations.
Sure, it'll run just as fast as the equivalent with actual variable
names; but that's beside the point. It takes extra effort to maintain
such code, and that is what matters.


That's exactly my point. Readability is what counts, especially for 
maintaining. "gcd(diff, n)" is a great name, much better than "g", if 
you ask me.


We aren't talking about 1000 lines of code here. The new syntax will 
enable one-liner optimizations. And I think Tim's example is as good as 
we can get realistically. Because if the expressions become longer or 
more complex and/or the numbers of expressions increase, I doubt that a 
majority want to have that in a single line even though the syntax would 
allow this. And if so the editor might include some line wraps, so then 
we are where we were before. Somewhere, you need to get your hands dirty.

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Barry Warsaw
On Apr 23, 2018, at 13:01, Ethan Furman  wrote:
> 
> On 04/22/2018 10:44 PM, Tim Peters wrote:
>> 
>> 
>> I find myself warming more to binding expressions the more I keep them
>> in mind while writing new code.

And I really like the term “binding expressions” because that’s how I think 
about this feature. I also think it will be easier to explain because “all it 
does” is bind a value to a name, and to me that’s the most powerful and 
valuable thing behind this feature.

> So I really like being able to make the assignment in the expression, but I 
> have a really hard time parsing it with the name first.

Me too.  Plus we *already* have precedence for spelling name bindings in 
similar constructs, such as import statements, with statements, and exceptions. 
 It seems like a natural and Pythonic approach to extend that same spelling to 
binding expressions rather than introducing new, weird, symbols.

I also think it effectively solves the switch-statement problem:

if (get_response() as answer) == 'yes':
do_it()
elif answer == 'no':
skip_it()
elif answer == 'maybe'
okay_then()

That’s Pythonic enough for jazz!

-Barry



signature.asc
Description: Message signed with OpenPGP
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Chris Angelico
On Tue, Apr 24, 2018 at 6:21 AM, Sven R. Kunze  wrote:
> On 23.04.2018 19:24, Chris Angelico wrote:
>>
>> On Tue, Apr 24, 2018 at 3:13 AM, Sven R. Kunze  wrote:
>>>
>>> diff = x - x_base
>>> if diff and gcd(diff, n) > 1:
>>>  return gcd(diff, n)
>>>
>>> # or
>>>
>>> if (x - x_base) and gcd(x - x_base, n) > 1:
>>>  return gcd(x - x_base, n)
>>>
>>>
>>> and have the interpreter handle the optimization, or apply an lru_cache?
>>> ;-)
>>
>> And then you want to change something, and you have to make an edit in
>> two places. Or, worse, you make it in only one of those places, they
>> become desynchronized, and nobody can figure out why the program
>> occasionally and bizarrely fails.
>
>
> If you change any of those lines (including ones of my fore-posters) without
> knowing what you're doing, you'd better don't touch them at all.
>
> The SQL folks btw. are pretty okay'ish with this kind of duplication because
> they can resolve it. Surely, Python isn't SQL but sometimes I wish Python
> could handle such things as easily without me having to babysit it all the
> time and using Perl'ish syntax (which := looks like to me). We then have :=,
> = and ==. Sorry, but Python wouldn't fit my brain then.
>

Ah, are you one of those programmers who writes code once and it's
instantly perfect? I apologize, I didn't realize I was in the presence
of a unicorn.

Most programmers will end up making edits to all non-trivial code. And
if your code is laid out in such a way that edits are easier and
safer, you're less likely to introduce bugs as you edit. Duplication
works against that by forcing you to make changes in two places.

I've seen code that relies on duplication and compiler optimizations.
Sure, it'll run just as fast as the equivalent with actual variable
names; but that's beside the point. It takes extra effort to maintain
such code, and that is what matters.

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] PEP 572: Assignment Expressions

2018-04-23 Thread Sven R. Kunze

On 23.04.2018 19:31, Tim Peters wrote:

Surely you're joking.  This is math.gcd(), which is expensive for
multi-thousand bit integers, and the interpreter knows nothing about
it.  Adding a cache of _any_ kind (LRU or otherwise) would make it
even slower.
Alright, if that problem is just about performance, then there must be a 
better way to resolve it rather than inventing a new syntax. Btw. 
storing the result in a local var is also a cache IMHO. And if gcd is 
immutable, I think Python can do a great job here of optimizing.


Anyway, your example is the best one I've seen so far.

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Sven R. Kunze

On 23.04.2018 19:24, Chris Angelico wrote:

On Tue, Apr 24, 2018 at 3:13 AM, Sven R. Kunze  wrote:

diff = x - x_base
if diff and gcd(diff, n) > 1:
 return gcd(diff, n)

# or

if (x - x_base) and gcd(x - x_base, n) > 1:
 return gcd(x - x_base, n)


and have the interpreter handle the optimization, or apply an lru_cache? ;-)

And then you want to change something, and you have to make an edit in
two places. Or, worse, you make it in only one of those places, they
become desynchronized, and nobody can figure out why the program
occasionally and bizarrely fails.


If you change any of those lines (including ones of my fore-posters) 
without knowing what you're doing, you'd better don't touch them at all.


The SQL folks btw. are pretty okay'ish with this kind of duplication 
because they can resolve it. Surely, Python isn't SQL but sometimes I 
wish Python could handle such things as easily without me having to 
babysit it all the time and using Perl'ish syntax (which := looks like 
to me). We then have :=, = and ==. Sorry, but Python wouldn't fit my 
brain then.

___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Ethan Furman

On 04/22/2018 10:44 PM, Tim Peters wrote:

[Guido]

In reality there often are other conditions being applied to the match for
which `if expr as name` is inadequate. The simplest would be something like

   if ...:
   
   elif (m := re.match('(.*):(.*)', line)) and m.group(1) == m.group(2):
 

And the match() call may not even be the first thing to check -- e.g. we
could have

 elif line is not None and (m := re.match('(.*):(.*)', line)) and 
m.group(1) == m.group(2):


I find myself warming more to binding expressions the more I keep them
in mind while writing new code.  And I think it may be helpful to
continue showing real examples where they would help.

Today's example:  I happened to code this a few hours ago:

diff = x - x_base
if diff:
 g = gcd(diff, n)
 if g > 1:
 return g

It's not really hard to follow, but two levels of nesting "feels
excessive", as does using the names "diff" and "g" three times each.
It's _really_ an "and" test:  if the diff isn't 0 and gcd(diff, n) >
1, return the gcd.  That's how I _thought_ of it from the start.

Which this alternative expresses directly:

if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
 return g


So I really like being able to make the assignment in the expression, but I have a really hard time parsing it with the 
name first.


Attempting to read just the names first:

  if
diff
  scan for ending right paren
  found
  and
 g
  scan for ending right paren
oops, found opening left paren
scan for ending right paren
found
  resume scanning for final right paren
  found
 > 1:
 return g


Attempting to read expressions first:

  if
x - x_base
  and
gcd(diff, n)
  what's diff?
scan backwards
  diff is x - x_base
> 1:
return g
  what's g?
scan up and backwards
g is gcd(diff, n)


Attempting to read interleaved:

  if
skip diff
  x - x_base
  back to diff
as diff
  and
skip g
  gcd(diff, n)
  back to g
as g
  > 1:
  return g


On the other hand, if it were using the "as" keyword:

if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
return g

I would parse as:

  if
x - x_base
as diff
  and
gcd(diff, n)
as g
  > 1:
  return g

For me at least, the last is much more readable.  Thinking about it some more, the problem (or maybe just my problem) is 
that I see an "if" or "while" and the I look for the thing that is True or False, and using the ":=" syntax the first 
thing I see is a placeholder for a result that doesn't exist yet, making me constantly scan backwards and forwards to 
put all the pieces in the correct place.


With "as", it just flows forwards.

--
~Ethan~
___
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] PEP 573 -- Module State Access from C Extension Methods

2018-04-23 Thread Petr Viktorin

On 04/23/18 14:04, Jeroen Demeyer wrote:

Hello,

I just saw this PEP. There is a bit of overlap between PEP 573 and PEP 
575 since these both change the calling convention for built-in methods. 
In particular, PEP 575 also proposes to add a "defining class" member 
(for different reasons). In PEP 575, this is added to the PyCFunction 
struct itself instead of a separate struct PyCMethod.


The reason you just saw the pep is because it wasn't posted to 
python-dev yet, and it wasn't posted yet because we first want to look 
for potential conflicts with 573.


(There's no one forking on PEP 573 full-time, so unfortunately it's 
progressing slower than I'd like.)


It would be nice to justify whether you really need a new class 
(PyCMethod_Type) to support METH_METHOD. It looks strange to me that the 
class of some object depends on an implementation detail like whether 
METH_METHOD is specified.


The current PEP 573 implies that backwards compatibility concerns would 
arise every time that METH_METHOD is added to an existing method. People 
have asked questions on PEP 575 about that: it would break code 
depending on "types.BuiltinFunctionType" for example. You could instead 
just change PyCFunctionObject to add that field (that's what I did in 
PEP 575).


For practical reasons, it would be nice to implement PEP 573 and PEP 575 
together as they affect the same code (assuming that both PEPs are 
accepted of course).


I currently even think PEP 575 can go forward *before* PEP 573. Having 
__objclass__ on methods of extension classes does sounds like a more 
elegant solution! And for PEP 573 it would mean one less annoying 
problem to solve.



Reading PEP 575, I miss an explanation of what __objclass__ *is* -- it 
only says the technical restrictions on it. For PEP 575 I found it 
pretty important that the reader gets a good mental picture of what it 
is, but it's a bit difficult to explain succinctly.

Maybe something like this would help make it clearer in PEP 573?

If set, `__objclass__` is the class that defines the method (which might 
be a superclass of `type(self)`). Functionally it's equivalent to the 
`__class__` cell [0] in Python code.


[0] 
https://docs.python.org/3/reference/datamodel.html#creating-the-class-object


___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Antoine Pitrou
On Mon, 23 Apr 2018 16:59:35 +0100
Steve Holden  wrote:
> On Mon, Apr 23, 2018 at 8:28 AM, Antoine Pitrou  wrote:
> 
> > On Mon, 23 Apr 2018 00:44:44 -0500
> > Tim Peters  wrote:
> > ​[...]
> >  
> > > if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
> > > return g
> > > That's so Pythonic I could cry ;-)  
> >
> > ​[...]
> >
> > The second part, especially, where you use the result of an
> > assignment expression as a comparison operand, looks definitely
> > un-Pythonic.
> >
> ​Which, I suppose, underlines that Pythonicity is in the mind of the  
> beholder.​

Indeed it is.  What we can only say is that the proposed idiom goes
against current Python syntactical rules :-)

> The assignment expression seems like a vary natural way to introduce
> variables of limited (controlled?) scope, [...]

AFAIU, the scope isn't limited to the "if" block, it's a regular local
variable.  I might have misread.

> While Tim's expression might look (superficially) like C, the five-line
> alternative isn't exactly an inspiring example of Pythonicity, is it?

I don't know.  I've written my share of similar-looking code and I've
never really been bothered, at least not enough that I thought we
should change the language to accomodate those use cases.  To be frank
I don't remember the last time I was bothered by an aspect of Python's
syntax.  I think the language has reached "peak syntax" by now and it
should basically be frozen, and any improvements targeted at other
aspects (semantics, performance, stdlib, etc.).

Regardless, my three questions about this are:
- does it make Python more powerful?
- does it make Python more readable?
- does it make Python easier to learn and teach?

My answer would be "no" to all three, but YMMV.

Regards

Antoine.
___
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] PEP 573 -- Module State Access from C Extension Methods

2018-04-23 Thread Jeroen Demeyer

Hello,

I just saw this PEP. There is a bit of overlap between PEP 573 and PEP 
575 since these both change the calling convention for built-in methods. 
In particular, PEP 575 also proposes to add a "defining class" member 
(for different reasons). In PEP 575, this is added to the PyCFunction 
struct itself instead of a separate struct PyCMethod.


It would be nice to justify whether you really need a new class 
(PyCMethod_Type) to support METH_METHOD. It looks strange to me that the 
class of some object depends on an implementation detail like whether 
METH_METHOD is specified.


The current PEP 573 implies that backwards compatibility concerns would 
arise every time that METH_METHOD is added to an existing method. People 
have asked questions on PEP 575 about that: it would break code 
depending on "types.BuiltinFunctionType" for example. You could instead 
just change PyCFunctionObject to add that field (that's what I did in 
PEP 575).


For practical reasons, it would be nice to implement PEP 573 and PEP 575 
together as they affect the same code (assuming that both PEPs are 
accepted of course).



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] PEP 572: Assignment Expressions

2018-04-23 Thread Tim Peters
[Sven R. Kunze ]
> What about
>
> diff = x - x_base
> if diff and gcd(diff, n) > 1:
> return gcd(diff, n)
>
> # or
>
> if (x - x_base) and gcd(x - x_base, n) > 1:
> return gcd(x - x_base, n)
>
>
> and have the interpreter handle the optimization, or apply an lru_cache? ;-)

Surely you're joking.  This is math.gcd(), which is expensive for
multi-thousand bit integers, and the interpreter knows nothing about
it.  Adding a cache of _any_ kind (LRU or otherwise) would make it
even slower (in the application, there's no reason to expect that x -
x_base will repeat a value before O(sqrt(n)) iterations, which itself
can be thousands of bits - a cache hit would be a miracle).
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Chris Angelico
On Tue, Apr 24, 2018 at 3:13 AM, Sven R. Kunze  wrote:
> On 23.04.2018 17:59, Steve Holden wrote:
>
>
> While Tim's expression might look (superficially) like C, the five-line
> alternative isn't exactly an inspiring example of Pythonicity, is it?
>
>
> What about
>
> diff = x - x_base
> if diff and gcd(diff, n) > 1:
> return gcd(diff, n)
>
> # or
>
> if (x - x_base) and gcd(x - x_base, n) > 1:
> return gcd(x - x_base, n)
>
>
> and have the interpreter handle the optimization, or apply an lru_cache? ;-)

And then you want to change something, and you have to make an edit in
two places. Or, worse, you make it in only one of those places, they
become desynchronized, and nobody can figure out why the program
occasionally and bizarrely fails. Removing duplicate function calls
isn't just about run-time performance.

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] PEP 572: Assignment Expressions

2018-04-23 Thread Sven R. Kunze

On 23.04.2018 17:59, Steve Holden wrote:


While Tim's expression might look (superficially) like C, the 
five-line alternative isn't exactly an inspiring example of 
Pythonicity, is it?




What about

diff = x - x_base
if diff and gcd(diff, n) > 1:
return gcd(diff, n)

# or

if (x - x_base) and gcd(x - x_base, n) > 1:
return gcd(x - x_base, n)


and have the interpreter handle the optimization, or apply an lru_cache? ;-)

Cheers,
Sven
___
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] PEP 572: Assignment Expressions

2018-04-23 Thread Steve Holden
On Mon, Apr 23, 2018 at 8:28 AM, Antoine Pitrou  wrote:

> On Mon, 23 Apr 2018 00:44:44 -0500
> Tim Peters  wrote:
> ​[...]
>
> > if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
> > return g
> > That's so Pythonic I could cry ;-)
>
> ​[...]
>
> The second part, especially, where you use the result of an
> assignment expression as a comparison operand, looks definitely
> un-Pythonic.
>
> ​Which, I suppose, underlines that Pythonicity is in the mind of the
beholder.​


The assignment expression seems like a vary natural way to introduce
variables of limited (controlled?) scope, and the class-namespace special
case doesn't seem horrible enough to put me, at least, off the idea. There
will, of course, be those who abuse assignment expressions, and I'm very
much looking forward to seeing what David Beazley makes of them.

While Tim's expression might look (superficially) like C, the five-line
alternative isn't exactly an inspiring example of Pythonicity, is it?

regards
 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] PEP 572: Assignment Expressions

2018-04-23 Thread Tim Peters
[Tim]
>> Which this alternative expresses directly:
>>
>> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
>> return g
>>
>> That's so Pythonic I could cry ;-)

[Antoine]
> It looks like C to me.  That won't make me cry (I write C++ code daily
> these days), but it's certainly not the same language as Python.
>
> The second part, especially, where you use the result of an
> assignment expression as a comparison operand, looks definitely
> un-Pythonic.

You snipped the part explaining _what's_ "Pythonic" about it:

It's _really_ an "and" test:  if the diff isn't 0 and gcd(diff, n) >
1, return the gcd.  That's how I _thought_ of it from the start.

"Expresses directly" is the Pythonic part; the syntax is minor to me.
Seeing that the _intent_ is an "and test" is a pattern-matching puzzle
in the original spelling (which essentially turned me into a compiler,
writing low-level code for the _concepts_ I had in mind from the
start):

diff = x - x_base
if diff:
g = gcd(diff, n)
if g > 1:
return g

But note that the part of the PEP I support is just the "binding
expression" part:  giving a simple name (binding an identifier) to the
result of an expression.  I don't want the full potential complexity
of assignment statements in expressions.  There's nothing
"un-Pythonic" about merely giving a name to an expression result,
apart from that there are few contexts that currently support that in
a sanely usable way.
___
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] PEP 573 -- Module State Access from C Extension Methods

2018-04-23 Thread Marcel Plch
Hello,
I am an intern at Red Hat mentored by Petr Viktorin. As a part of my
internship, I learned the CPython internals and how to contribute
to the CPython interpreter.

As a result, I have prepared PEP 573, which solves some problems
that PEP 489 (Multi-phase extension module initialization) has left open.
Specifically, this PEP proposes a way to access per-module state from methods of
built-in and extension types.
Like PEP 489, it aims to make subinterpreter-friendly built-in/extension modules
easier to create.

A big problem found when converting many modules to PEP 489 multi-phase
initialization is subinterpreter-friendly access to exception
types defined in built-in/extension modules.
This PEP solves this by introducing "immutable exception types".
The current implementation requires one new type flag and two new
pointers in the heap type structure.
It should be possible to remove eiher the flag or one of the two pointers,
if we agree on the other mechanics in the PEP .


===

PEP: 573
Title: Module State Access from C Extension Methods
Version: $Revision$
Last-Modified: $Date$
Author: Petr Viktorin ,
Nick Coghlan ,
Eric Snow ,
Marcel Plch 
Discussions-To: import-...@python.org
Status: Active
Type: Process
Content-Type: text/x-rst
Created: 02-Jun-2016
Python-Version: 3.8
Post-History:


Abstract


This PEP proposes to add a way for CPython extension methods to access
context such as
the state of the modules they are defined in.

This will allow extension methods to use direct pointer dereferences
rather than PyState_FindModule for looking up module state, reducing
or eliminating the
performance cost of using module-scoped state over process global state.

This fixes one of the remaining roadblocks for adoption of PEP 3121 (Extension
module initialization and finalization) and PEP 489
(Multi-phase extension module initialization).

Additionaly, support for easier creation of immutable exception
classes is added.
This removes the need for keeping per-module state if it would only be used
for exception classes.

While this PEP takes an additional step towards fully solving the
problems that PEP 3121 and PEP 489 started
tackling, it does not attempt to resolve *all* remaining concerns. In
particular, accessing the module state from slot methods (``nb_add``,
etc) remains slower than accessing that state from other extension
methods.


Terminology
===

Process-Global State


C-level static variables. Since this is very low-level
memory storage, it must be managed carefully.

Per-module State


State local to a module object, allocated dynamically as part of a
module object's initialization. This isolates the state from other
instances of the module (including those in other subinterpreters).

Accessed by ``PyModule_GetState()``.


Static Type
---

A type object defined as a C-level static variable, i.e. a compiled-in
type object.

A static type needs to be shared between module instances and has no
information of what module it belongs to.
Static types do not have ``__dict__`` (although their instances might).

Heap Type
-

A type object created at run time.


Rationale
=

PEP 489 introduced a new way to initialize extension modules, which brings
several advantages to extensions that implement it:

* The extension modules behave more like their Python counterparts.
* The extension modules can easily support loading into pre-existing
  module objects, which paves the way for extension module support for
  ``runpy`` or for systems that enable extension module reloading.
* Loading multiple modules from the same extension is possible, which
  makes testing module isolation (a key feature for proper sub-interpreter
  support) possible from a single interpreter.

The biggest hurdle for adoption of PEP 489 is allowing access to module state
from methods of extension types.
Currently, the way to access this state from extension methods is by
looking up the module via
``PyState_FindModule`` (in contrast to module level functions in
extension modules, which
receive a module reference as an argument).
However, ``PyState_FindModule`` queries the thread-local state, making
it relatively
costly compared to C level process global access and consequently
deterring module authors from using it.

Also, ``PyState_FindModule`` relies on the assumption that in each
subinterpreter, there is at most one module corresponding to
a given ``PyModuleDef``.  This does not align well with Python's import
machinery.  Since PEP 489 aimed to fix that,  the assumption does
not hold for modules that use multi-phase initialization, so
``PyState_FindModule`` is unavailable for these modules.

A faster, safer way of accessing module-level state from extension methods
is needed.


Immutable Exception Types

Re: [Python-Dev] PEP 572: Assignment Expressions

2018-04-23 Thread Antoine Pitrou
On Mon, 23 Apr 2018 00:44:44 -0500
Tim Peters  wrote:
> 
> Which this alternative expresses directly:
> 
> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
> return g
> 
> That's so Pythonic I could cry ;-)

It looks like C to me.  That won't make me cry (I write C++ code daily
these days), but it's certainly not the same language as Python.

The second part, especially, where you use the result of an
assignment expression as a comparison operand, looks definitely
un-Pythonic.

Regards

Antoine.


___
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