[Python-ideas] Path conversion for f-strings
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
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
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
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
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
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
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
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
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
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
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
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/