[Python-ideas] Path conversion for f-strings

2019-05-12 Thread Batuhan Taskaya
Like repr and string the file system path is used alot and something like
path!p might be handy.

>>> class MyClass:
... def __fspath__(self):
... return "/home/batuhan"
...
>>> assert f"{mc!p}" == f"{os.fspath(mc)}"

Also it saves us to unnecessarily import os for only fspath().
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread James Lu
I think a Python version of longjmp() and setjmp() might be easier to
understand.

On Sun, May 12, 2019 at 6:23 PM David Mertz  wrote:

> On Sun, May 12, 2019, 5:36 PM Paul Moore  wrote:
>
>> On Sun, 12 May 2019 at 21:06, David Mertz  wrote:
>> > I thought of 'as' initially, and it reads well as English. But it felt
>> to me like the meaning was too different from the other meanings of 'as' in
>> Python. I might be persuaded otherwise.
>>
>> If you think in terms of "named loops" rather than "labels", "as"
>> makes a lot more sense.
>
>
> Every name created with 'as' currently is a regular Python object, with a
> memory address, and some methods, that can participate in comparison (at
> least equality), that has a type, can be passed as a function argument,
> etc. Actually, all that is true of EVERY name in Python other than keywords.
>
> It seems like none of this would be true of a loop name/label. Hence my
> first thought that a different way of introducing the word is more clear...
> Maybe we can just prefix lines with labels instead, and add a 'goto'
> command :-)
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread David Mertz
On Sun, May 12, 2019, 5:36 PM Paul Moore  wrote:

> On Sun, 12 May 2019 at 21:06, David Mertz  wrote:
> > I thought of 'as' initially, and it reads well as English. But it felt
> to me like the meaning was too different from the other meanings of 'as' in
> Python. I might be persuaded otherwise.
>
> If you think in terms of "named loops" rather than "labels", "as"
> makes a lot more sense.


Every name created with 'as' currently is a regular Python object, with a
memory address, and some methods, that can participate in comparison (at
least equality), that has a type, can be passed as a function argument,
etc. Actually, all that is true of EVERY name in Python other than keywords.

It seems like none of this would be true of a loop name/label. Hence my
first thought that a different way of introducing the word is more clear...
Maybe we can just prefix lines with labels instead, and add a 'goto'
command :-)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread David Mertz
On Sun, May 12, 2019, 3:33 PM Gustavo Carneiro  wrote:

> # Hypothetical future labelled break:
>> def find_needle_in_haystacks():
>> for haystack in glob.glob('path/to/stuff/*') label HAYSTACKS:
>> fh = open(fname)
>> header = fh.readline()
>> if get_format(header) == 'foo':
>> for line in fh:
>> if process_foo(line) == -1:
>> break HAYSTACKS
>> elif get_format(header) == 'bar':
>> for line in fh:
>> if process_bar(line) == -1:
>> break HAYSTACKS
>>
>
> Nice.  Suggestion:
> 1. replace "label HAYSTACKS" with "as HAYSTACKS", if possible, so no new
> keyword is introduced;
> 2. replace "break HAYSTACKS" with "break from HAYSTACKS"
>

I thought of 'as' initially, and it reads well as English. But it felt to
me like the meaning was too different from the other meanings of 'as' in
Python. I might be persuaded otherwise.

Likewise, 'from' isn't really very similar to other existing uses.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread David Mertz
I thought of "we could return immediately" shortly after I posted it. Yes,
that's true in the example I wrote. But it's easy enough to vary it so that
something happens after the loop as well. I also noticed that for the
simple version, it might be slightly shorter to put the conditional inside
the loop rather than to decide between loops.

There are lots of ways to work around the absence of a labelled break. Many
times putting the inner loop in a comprehension can simplify things too,
for example (that's roughly what my actual code was refactored to, mostly
not just because of the break issue).

On Sun, May 12, 2019, 3:38 PM Chris Angelico  wrote:

> On Mon, May 13, 2019 at 3:26 AM David Mertz  wrote:
> >
> > To be clear in this thread, I don't think I'm really ADVOCATING for a
> multi-level break.  My comments are simply noting that I personally fairly
> often encounter the situation where they would be useful.  At the same
> time, I worry about Python gaining sometimes-useful features that
> complicate the overall language and bring it closer to Perl's "everyone can
> write in their own style."
> >
> > So to answer Chris' question... well, i did find something recent, but
> it has a ton of other extraneous stuff.  But I've simplified to something
> that isn't that much different from my example from my tablet yesterday,
> but is fairly realistic still.
> >
> > I have an existing function that looks roughly like this:
> >
> > def find_needle_in_haystacks():
> > found_needle = False
> > for haystack in glob.glob('path/to/stuff/*'):
> > fh = open(fname)
> > header = fh.readline()
> > if get_format(header) == 'foo':
> > for line in fh:
> > status = process_foo(line)
> > if status = -1:
> > found_needle = True
> > break
> > elif get_format(header) == 'bar':
> > for line in fh:
> > status = process_bar(line)
> > if status = -1:
> > found_needle = True
> > break
> >
> > if found_needle:
> > break
> >
>
> Cool. How much code is there AFTER this loop? The most obvious way to
> handle this is to immediately 'return' instead of multi-level
> breaking.
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread Gustavo Carneiro
On Sun, 12 May 2019 at 18:26, David Mertz  wrote:

> To be clear in this thread, I don't think I'm really ADVOCATING for a
> multi-level break.  My comments are simply noting that I personally fairly
> often encounter the situation where they would be useful.  At the same
> time, I worry about Python gaining sometimes-useful features that
> complicate the overall language and bring it closer to Perl's "everyone can
> write in their own style."
>
> So to answer Chris' question... well, i did find something recent, but it
> has a ton of other extraneous stuff.  But I've simplified to something that
> isn't that much different from my example from my tablet yesterday, but is
> fairly realistic still.
>
> I have an existing function that looks roughly like this:
>
> def find_needle_in_haystacks():
> found_needle = False
> for haystack in glob.glob('path/to/stuff/*'):
> fh = open(fname)
> header = fh.readline()
> if get_format(header) == 'foo':
> for line in fh:
> status = process_foo(line)
> if status = -1:
> found_needle = True
> break
> elif get_format(header) == 'bar':
> for line in fh:
> status = process_bar(line)
> if status = -1:
> found_needle = True
> break
>
> if found_needle:
> break
>
> If I had a "labelled break" feature, I might rewrite it something like the
> following (picking convenient syntax that I'm not per-se advocating as
> best, even if the concept is adopted):
>
> # Hypothetical future labelled break:
> def find_needle_in_haystacks():
> for haystack in glob.glob('path/to/stuff/*') label HAYSTACKS:
> fh = open(fname)
> header = fh.readline()
> if get_format(header) == 'foo':
> for line in fh:
> if process_foo(line) == -1:
> break HAYSTACKS
> elif get_format(header) == 'bar':
> for line in fh:
> if process_bar(line) == -1:
> break HAYSTACKS
>
>
Nice.  Suggestion:
1. replace "label HAYSTACKS" with "as HAYSTACKS", if possible, so no new
keyword is introduced;
2. replace "break HAYSTACKS" with "break from HAYSTACKS"



> In any case, it's often possible to either (a) redefine the inner loop
>>> as some sort of container operation, or (b) redefine the outer
>>> operation as a function, and use "return". So it would be helpful to
>>> have an example that CAN'T be rewritten in one of those ways, to use
>>> as a compelling example.
>>>
>>
> --
> Keeping medicines from the bloodstreams of the sick; food
> from the bellies of the hungry; books from the hands of the
> uneducated; technology from the underdeveloped; and putting
> advocates of freedom in prisons.  Intellectual property is
> to the 21st century what the slave trade was to the 16th.
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Gustavo J. A. M. Carneiro
Gambit Research
"The universe is always one step beyond logic." -- Frank Herbert
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread David Mertz
To be clear in this thread, I don't think I'm really ADVOCATING for a
multi-level break.  My comments are simply noting that I personally fairly
often encounter the situation where they would be useful.  At the same
time, I worry about Python gaining sometimes-useful features that
complicate the overall language and bring it closer to Perl's "everyone can
write in their own style."

So to answer Chris' question... well, i did find something recent, but it
has a ton of other extraneous stuff.  But I've simplified to something that
isn't that much different from my example from my tablet yesterday, but is
fairly realistic still.

I have an existing function that looks roughly like this:

def find_needle_in_haystacks():
found_needle = False
for haystack in glob.glob('path/to/stuff/*'):
fh = open(fname)
header = fh.readline()
if get_format(header) == 'foo':
for line in fh:
status = process_foo(line)
if status = -1:
found_needle = True
break
elif get_format(header) == 'bar':
for line in fh:
status = process_bar(line)
if status = -1:
found_needle = True
break

if found_needle:
break

If I had a "labelled break" feature, I might rewrite it something like the
following (picking convenient syntax that I'm not per-se advocating as
best, even if the concept is adopted):

# Hypothetical future labelled break:
def find_needle_in_haystacks():
for haystack in glob.glob('path/to/stuff/*') label HAYSTACKS:
fh = open(fname)
header = fh.readline()
if get_format(header) == 'foo':
for line in fh:
if process_foo(line) == -1:
break HAYSTACKS
elif get_format(header) == 'bar':
for line in fh:
if process_bar(line) == -1:
break HAYSTACKS

In any case, it's often possible to either (a) redefine the inner loop
>> as some sort of container operation, or (b) redefine the outer
>> operation as a function, and use "return". So it would be helpful to
>> have an example that CAN'T be rewritten in one of those ways, to use
>> as a compelling example.
>>
>
-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] add an additional dataclasses.asdict option for non-dataclasses

2019-05-12 Thread Christopher Barker
On Sat, May 11, 2019 at 8:23 PM Eric V. Smith  wrote:

>
>> https://www.python.org/dev/peps/pep-0557/#why-not-just-use-namedtuple
>>
>
> you would know, but that reference talks about why they are not the same
> as NamedTuple.
>
>
> That section mentions why they’re not iterable. Search on “iterable”.
>

Sure, but in the context of the difference with NamedTuple:

"""
Instances are always iterable, which can make it difficult to add fields.
If a library defines:

Time = namedtuple('Time', ['hour', 'minute'])
def get_time():
return Time(12, 0)

Then if a user uses this code as:

hour, minute = get_time()

then it would not be possible to add a second field to Time without
breaking the user's code.
"""

which is a great argument for why you wouldn't want dataclasses to iterate
on the *values* of the fields, which is what NamedTuple does. In fact,
beyond iteration, NamedTuple, IS a tuple, so:

- the number of "fields" matters,
- the order of the "fields" matters,
- it's the values that really matter -- the field names are incidental.

None of this (intentionally) applies to dataclasses - which is what i took
as the point of that section of the PEP.

But I see dataclasses as being more analogous to a dict than a tuple:

- The field names matter
- The order of the fields does not matter (the current state of the dict
implementation not withstanding)

So *if* dataclasses were to be iterable, then I'd think they should either
implement the Mapping protocol (which would make them, similar to
NamedTuple, a drop-in replacement for a dict, or iterate over (field_name,
value) pairs. which would not introduce the issues staed in teh PEP with
the iterability of NamedTuple.

Note: I am NOT advocating for making dataclasses a Mapping -- I believe in
a clear separation between "data" and "code" -- dicts are suitable for
data, and dataclasses are suitable for code. Given PYthon's dynamic nature,
this isn't always a clear boundary, but I think it's a better not to
purposely make it even less clear.

Others may have a different take on this -- it could be kind of a cool way
to make a dict with extra functionality, but I think that's ill-advised.

> if dataclasses *were*iterable, they almost certainly wouldn't iterate over
> the values alone.
>
> That wouldn’t make a difference. The given NT example would still be a
> problem.
>

you know, I'm embarrassed to say that I read through a lot of this thread
wondering what the heck an NT is ;-) -- but now I got it.

but I don't think the NT example is relevant here -- it's an issue with NT,
because NTs are designed to be, and used as drop in replacements of tuples,
and a lot of code out there does use tuples for "unpacking" assignments.

But I'm going to hazard a guess that it's pretty rare for folks to do:

def get_time():
...
return {"hour", 3, "minute", 5}

hour, minute = get_time()

and:

result = get_time()
hour = result['hour']
minute = results["minute"]

wouldn't break, now would:

time_dict = dict(get_time())

Anyway, we need dataclasses AND NamedTuples because dataclasses down't
behave like a tuple -- but that doesn't mean that they couldn't behave more
like a dict in some ways.

> And my toy code actually adds another decorator to make dataclasses
> iterable, so it would be a completely optional feature.
>
>
> That approach of adding support for iterability makes sense to me. I’m
> contemplating adding a “dataclasses_tools” package for some other tools I
> have.
>

I like that -- good idea. If any of my toy code is useful, please feel free
to make use of it.


> But I’m not sure how this fits in to the asdict discussion.
>

Well, it fits in in the sense that the question at hand is:

Is there a need for a standard protocol for making dicts out of arbitrary
classes?

datacalsses were used as an example use-case, as datacalsses do naturally
map to dicts.

My point is that there are already two protocols for making an arbitrary
classes into a dict, so I don't think we need another one. Even though
those two are overloading other use cases: the Mapping ABC and iteration.

This does mean that there would be no way to shoehorn NamedTuples into this
-- as they already use the iteration protocol in a way that is incompatible
with dict creation. So yeah, maybe a use case there.

But the other option is to use a convention, rather than an official
protocol -- if an object has an "asdict()" method, then that method returns
a dict. pretty simple.

If you were dealing with arbitrary objects, you'd have to write code like:

try:
a_dict = an_object.asdict()
except (AttributeError, Type Error):
a_dict = something_else

but you'd need to do that anyway, as you couldn't count on every type being
conformant with the dict() constructor anyway.

So I'm still trying to see the use cases for having wanting to turn
arbitrary objects into dicts.

As for NamedTuple -- it does have _asdict:

In [122]: p._asdict()

Out[122]: OrderedDict([('x', 4), ('y', 5)])

(sidenote --now that 

Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread MRAB

On 2019-05-12 10:44, Steven D'Aprano wrote:

On Sun, May 12, 2019 at 11:16:21AM +0200, Oleg Broytman wrote:

On Sun, May 12, 2019 at 01:36:28AM -0700, Elias Tarhini  
wrote:
> If I may propose `break n` as a replacement for the original message's
> `break break ... break`, where n>0 is the number of contiguous loops to
> break out of and `break 1` is synonymous with `break`. Seems easier on my
> eyes/noggin than counting out the individual `break` statements.

   This is very much error-prone because on any refactoring (increasing
or decreasing the number of loop levels) one must increase/decrease all
numbers in internal loops.

   Labels are at least stable.


Indeed.

Go has labels for loops:

 Label:
 for { ...
   break Label
 }

as does Rust:

 'label: while condition:
{
 ...
 break label
 }

We can't use the same syntax in Python, but we might write it like this:

 @label while condition:
 block
 break label

and similar with for loops:

 @outer for x in range(100):
 @inner for y in range(3):
 if x == y == 1: break  # like ``break inner``
 if x == y == 2: break outer
 print(x, y)
 # break inner jumps to here
 # break outer jumps to here


@ reminds me too much of decorators.

How about this:

 while condition:
block
break label


 for x in range(100):
 for y in range(3):
if x == y == 1: break  # like ``break inner``
if x == y == 2: break outer
print(x, y)
# break inner jumps to here
# break outer jumps to here
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread haael




The concrete example I was working on when I started to miss double 
break. This is an implementation of polynomial long division in Galois 
field. Almost unmodified.


With outer break, I would't need to use the `running` variable. In fact, 
for mathematical clarity, I would like to put a test in the outer loop, 
like: `while dividend`. It would make clear what this algorithm is 
actually doing.


Sure, it could be refactored, but it would lose the relative simplicity. 
For such operations it is sometimes important to remain close to the raw 
mathematical notation.





def __divmod__(self, other):
dividend = self.canonical()

try:
divisor = other.canonical()
except AttributeError:
return NotImplemented

if not dividend:
return Field.zero(self.size), Field.zero(self.size)

try:
d = next(iter(divisor)) # leading term of the divisor
except TypeError:
d = self.const(divisor)

do = self.__monomial_order(d)

result = Field.zero(self.size)
running = True
while running: # outer loop, retry the changing `dividend`
for x in dividend: # yield all monomials from this polynomial
if self.__monomial_order(x) < do:
# encountered monomial of too small order, finish
running = False
break # exit outer loop
try:
c = self.__monomial_division(x, d) # may fail
assert c # sanity check
result += c
dividend -= c * divisor
dividend = dividend.canonical()
# if `dividend` nonzero, try again
# if `dividend` is zero, finish
running = bool(dividend)
break
except ArithmeticError:
# monomial division failed, try next one
continue # inner loop
else:
# `dividend` exhausted, finish
running = False
pass

if not hasattr(result, 'operator'):
result = self.const(result)

return result.canonical(), dividend.canonical()

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread Steven D'Aprano
On Sun, May 12, 2019 at 11:16:21AM +0200, Oleg Broytman wrote:
> On Sun, May 12, 2019 at 01:36:28AM -0700, Elias Tarhini  
> wrote:
> > If I may propose `break n` as a replacement for the original message's
> > `break break ... break`, where n>0 is the number of contiguous loops to
> > break out of and `break 1` is synonymous with `break`. Seems easier on my
> > eyes/noggin than counting out the individual `break` statements.
> 
>This is very much error-prone because on any refactoring (increasing
> or decreasing the number of loop levels) one must increase/decrease all
> numbers in internal loops.
> 
>Labels are at least stable.

Indeed.

Go has labels for loops:

Label:
for { ...
  break Label
}

as does Rust:

'label: while condition:
   {
...
break label
}

We can't use the same syntax in Python, but we might write it like this:

@label while condition:
block
break label

and similar with for loops:

@outer for x in range(100):
@inner for y in range(3):
if x == y == 1: break  # like ``break inner``
if x == y == 2: break outer
print(x, y)
# break inner jumps to here
# break outer jumps to here


-- 
Steven
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Break multiple loop levels

2019-05-12 Thread Oleg Broytman
On Sun, May 12, 2019 at 01:36:28AM -0700, Elias Tarhini  
wrote:
> If I may propose `break n` as a replacement for the original message's
> `break break ... break`, where n>0 is the number of contiguous loops to
> break out of and `break 1` is synonymous with `break`. Seems easier on my
> eyes/noggin than counting out the individual `break` statements.

   This is very much error-prone because on any refactoring (increasing
or decreasing the number of loop levels) one must increase/decrease all
numbers in internal loops.

   Labels are at least stable.

> Eli

Oleg.
-- 
Oleg Broytmanhttps://phdru.name/p...@phdru.name
   Programmers don't die, they just GOSUB without RETURN.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/