[Python-ideas] Re: Dict unpacking assignment
I really like this style of programming, especially after fooling around with Rust a lot, where pattern matching and its variations, like "if let" are working really well. I also like the idea of using the walrus operator in this use case, while it is probably up for a lot of discussing if the walrus operator should/can be reimplemented like this. With this pattern matching movement (PEP 622, 634, 636) this idea fits right in. A downside IMO is the readability. In the patter matching proposed in PEP 636, we introduce verbosity, while preserving readability. Every case is clearly readable. In your example I had to look twice that the 'Response' is the pattern which is matched from the 'get' result. But in the end this argument also applies to the already implemented walrus operator, so there is that. Patrick ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/XOO5E4U4KBJ7O4EC4H7MKQYRKFU3SHPW/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Experimental syntax proposal
On Sat, 24 Oct 2020 at 21:49, André Roberge wrote: > No, it does not. It proposes actual changes to the Python interpreter. > > Under my proposal, something like what is proposed there would first be > implemented as a third party package. > Not sure, but yes, the PEP proposes a change to the interpreter, but in such a way that you can define your own macro, ie custom keyword(s) in a third party package that can be import!ed. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/LIS4HZL6B7T7PG2AKO2UCL66PHYTDYH4/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Dict unpacking assignment
Steven D'Aprano wrote: > # Dotted names > from types import SimpleNamespace > obj = SimpleNamespace() > obj.spam = **{'obj.spam': 1} > assert obj.spam == 1 > > # Subscripts > arr = [None]*5 > arr[1], arr[3] = **{'arr[3]': 33, 'arr[1]': 11} > assert arr == [None, 11, None, 33, None] Currently in Python `arr[1]` is the same as `arr[ 1 ]` (notice the added spaces). How is it taken into account in you proposal, does one match and the other doesn't ? Are those line equivalent or not : arr[1], arr[3] = **{'arr[3]': 33, 'arr[1]': 11} arr[ 1 ], arr[ 3 ] = **{'arr[3]': 33, 'arr[1]': 11} arr[1], arr[3] = **{'arr[ 3 ]': 33, 'arr[ 1 ]': 11} If not that would mean that the style of writing changes the execution of the program, which was never the case before AFAIK. Joseph ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/MQB3M4EYCLVRJDSWATULUTTFDX3VJK6F/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Dict unpacking assignment
I think that instead of dict unpacking specifically, what we need is to come up with a way to use the pattern-matching proposed in PEP 634 outside of match statements. This would make it possible to unpack any pattern. My opinion is that the walrus operator is practically waiting to support pattern-matching: if Response(status=200, json={"title": title}) := get('/posts/42'): print(title) I wrote a few more examples here: - https://mail.python.org/archives/list/python-ideas@python.org/thread/MJ7JHYKHKB2T4SCFV4TX4IMKUANUAF5B/ -- Valentin ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ZWFMZH7QCOQHXPFGHAWOI74OSUAPCWGL/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Extrapolating PEP 634: The walrus was waiting for patmat all along
> Why should a failed match return None? That's not helpful if it matches > but the value itself is None. The only pattern that would match `None` is this one: print(None := get_value()) # Always None Here, the walrus operator would always return `None`. Either because the function returned `None` or the function returned something else and the pattern didn't match. The behavior is consistent, this particular pattern is just not that useful. Pattern-matching shouldn't exempt you from checking for `None` with the `is` operator anyway: print(get_value() is None) # True or False The proposed semantics don't get in the way of idiomatic python. Most of the time you only care about the truthiness of the value returned by the walrus operator. The most common example would be with regular expressions: price_tag = "Price: $7" if match := re.match(r".*(\d+).*", price_tag): print(match[1]) By the way I'm hoping that with PEP 634 `Match` objects can become proper `collections.abc.Sequence` instances. This would allow regex destructuring: if [_, amount] := re.match(r".*(\d+).*", price_tag): print(amount) -- Valentin ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7GWNFOLPAASUZCXAXAAUWFX7APVGNM4X/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Dict unpacking assignment
On Sat, Oct 24, 2020, 3:47 PM Daniel Moisset wrote: > If you find PEP-634 a bit dry, you might give a try to PEP-636 (written in > an explanatory style rather than a hard-spec style). You can always go back > to PEP-634 for the precise details. > Thank you that looks really helpful! ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/CP66MHK3P65MIABLBE2O4IZBQVOKALX7/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Experimental syntax proposal
On Sat, Oct 24, 2020 at 4:39 PM Marco Sulla wrote: > See PEP 638: > https://www.python.org/dev/peps/pep-0638/ > > If I have understood well, it proposes what you want > No, it does not. It proposes actual changes to the Python interpreter. Under my proposal, something like what is proposed there would first be implemented as a third party package. André Roberge ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/FL3UUFEDAKRXDKJWZGYJJJOCYEQUESMO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Dict unpacking assignment
If you find PEP-634 a bit dry, you might give a try to PEP-636 (written in an explanatory style rather than a hard-spec style). You can always go back to PEP-634 for the precise details. On Fri, 23 Oct 2020 at 13:48, Ricky Teachey wrote: > Fwiw, although I see how PEP 634 has the potential to be incredibly > powerful and I'm not opposed to it, I've tried to read and understand it > twice and it is so overwhelming I still find the syntax inscrutable (I'm > sure I'll get it eventually). I think Steven's proposed idea has a lot of > merit even in a post PEP 634 universe because the syntax is just so easy to > understand right away. At least for me. > > Pattern matching seems like it will fall under a learn python course > section titled "advanced python topics". Dict unpacking is more of a > moderate python topic. > > Additionally, Alex Hall's suggestions for how to use the various proposals > for shortened dict display syntax, bringing Steven's proposal in line with > pattern matching syntax but not having to repeat key names, is a really > nice reconciliation of the too syntax ideas. > > And it would also allow something like this: > > {spam, eggs, 'def': def_, 'class': class_, **kwargs} = kwargs > > ...fixing the name collision problem. > > On Fri, Oct 23, 2020, 5:41 AM Alex Hall wrote: > >> On Fri, Oct 23, 2020 at 11:10 AM Steven D'Aprano >> wrote: >> >>> > but that doesn't make it make sense to write `... = **values` as you >>> > suggest. >>> >>> Iterator unpacking on a dict already works: >>> >>> py> d = {'a': 10, 'b': 20} >>> py> spam, eggs = d >>> py> spam, eggs >>> ('a', 'b') >>> >>> so we need to distinguish the iterator unpacking case from the dict >>> unpacking case. >> >> >> I understand that, I just don't think this particular method of >> distinguishing is sufficiently justified. >> >> (Heretical question: do we *really* need to distinguish it in syntax? >> Iterator unpacking a dict seems like a dumb idea, I wouldn't be sad if we >> broke compatibility there) >> >> To me it makes sense to use the same double star used in >>> dict unpacking inside dict displays and function calls. >>> >> >> It makes some sense, but overall it's still quite different to anything >> existing. Typically the mechanics of assignment are defined by symbols that >> come before the =. This applies to iterable unpacking, setting attributes >> and mapping items, and augmented assignment. Everything after = just a >> normal expression. >> >> The most obvious syntax is to just assign to a dict display: >> >> {'spam': spam, 'eggs': eggs, **kw} = kwargs # not **kwargs >> >> The meaning seems intuitive and obvious at a glance. And it's flexible if >> the variable names don't always match the keys. But it's verbose and >> repetitive in the common case where the names match. >> >> I think it would be great if we had a syntax for abbreviating normal >> dicts with 'same name' keys. We discussed a lot of options earlier this >> year, e.g: >> >> {**, spam, eggs} >> {:spam, :eggs} >> {{spam, eggs}} >> >> Then using the same syntax in both dict unpacking and dict displays as >> expressions would be intuitive and obvious. This would be valid, although >> redundant: >> >> {**, spam, eggs} = {**, spam, eggs} >> >> and it would still be easy to add cases where names don't match: >> >> {'sleep': duration, **, spam, eggs} = kwargs >> >> Also, unpacking nested dicts follows naturally, whether we have an >> abbreviated syntax or not: >> >> {'spam': {'eggs': eggs, 'foo': foo}, 'bar': bar} = {'spam': {'eggs': >> eggs, 'foo': foo}, 'bar': bar} >> >> As does unpacking in a loop: >> >> for {**, spam, eggs} in list_of_dicts: >> >> whereas I'm not sure what would be done in your proposal. Something like >> this? >> >> for spam, eggs in **list_of_dicts: >> ___ >> Python-ideas mailing list -- python-ideas@python.org >> To unsubscribe send an email to python-ideas-le...@python.org >> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >> Message archived at >> https://mail.python.org/archives/list/python-ideas@python.org/message/SNYIR4IUSTYYH6IQNMCQ5SUTORDPILO6/ >> Code of Conduct: http://python.org/psf/codeofconduct/ >> > ___ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/FK3A7XBCIRFGZCSBHF5NM2JVEURXCAV3/ > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at
[Python-ideas] Re: Extrapolating PEP 634: The walrus was waiting for patmat all along
> If you look in PEP 622 you'll see that there was a rejected idea `if > match ...` that's pretty similar. We nixed it because it just made the > PEP larger. For 3.11 we can consider something like this. Of course I understand the PEP is already pretty big. But if it goes through and we start thinking about extending it with `if match` statements, my point is that it would be worth considering extending the walrus operator instead :) ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/EEJ27EVCQJTAPTWO6SRRHOOARRLSJJVT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Conditional function/method/dict arguments assignments
I had many times the same idea: why can't we just "say" to the called function "use your own default"? I'm quite sure this is possible in a tricky way, since defaults are stored in the function object. Anyway, honestly I don't like your syntax proposal. ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/GFLFFS2JL4S7UKDF2OK57VCFVYA6O6RD/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: Experimental syntax proposal
See PEP 638: https://www.python.org/dev/peps/pep-0638/ If I have understood well, it proposes what you want ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/44NCSH4MCBVMTP6SI2LUI5A3GXHMDYVT/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Re: TextIOWrapper support for null-terminated lines
On 2020-10-24 at 12:29:01 -0400, Brian Allen Vanderburg II via Python-ideas wrote: > ... Find can output it's filenames in null-terminated lines since it > is possible to have newlines in a filename(yuck) ... Spaces in filenames are just as bad, and much more common: $ touch 'foo bar' $ find . -name 'foo bar' ./foo bar $ find . -name 'foo bar' -print | xargs ls -l ls: cannot access './foo': No such file or directory ls: cannot access 'bar': No such file or directory $ find . -name 'foo bar' -print0 | xargs -0 ls -l -rw-r--r-- 1 dan dan 0 Oct 24 13:31 './foo bar' $ rm 'foo bar' ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/F5UX5CL7YQIHEX3MP5R4GUVHIXCS5VQP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Conditional function/method/dict arguments assignments
This is just a hack idea I had for functions/methods that have parameters with default values, possibly outside the control of the user of said function, where sometimes it is desired to pass an argument to the function that differs from the default but other times it is desired to just use the default, whatever that may be # An external function def dosomething(count=5): doing_something # The function using an external function def dosomething_twice(count=None): # if count is none, just use the default count from dosomething if count is None: dosomething() dosomething() else: dosomething(count) dosomething(count) # or use a dict # kwargs = {} # if count is not None: # kwargs["count"] = count # dosomething(*kwargs) # dosomething(*kwargs) We could set the count's default value to 5 in dosomething_twice, but then if the external function changed its default, calling dosomething_twice with no parameters would no longer actually be using dosomething's default. If dosomething were in our control, we could set count=None as default and in the code do something like count = 5 if count is None else count. I imagine a syntax like def dosomething_twice(count=None): dosomething(count is not None ?? count) # If count is not None, pass it, else, use the dosomething's default parameter. dosomething(count is not None ?? count) This syntax is ?? . The requirements are that the parameter to be filled in in the calling method must have a default value. If the test evaluates to false, the right hand side will not be evaluated (lazy evaluation) and instead the default value will be used. This can also be used for passing by keyword arguments: def dosomething_twice(count=None): dosomething(count = count is not None ?? count) dosomething(count = count is not None ?? count) It could also be used to avoid specifying long argument lists: # external button.create(self, parent, x=0, y=0, w=64, h=32, style=, label="", windowclass="") calling: ??, by itself, will fill in that parameter with the default. If the external code ever changes, no need to change our code to update each time. The use case here is to skip specifying a parameter in a long function parameter list but still have its default used. This probably only make sense for parameters being passed via positional arguments, since "style=??", (pass as a keyword style the default value), can just be done by omitting style call. def create_buttons(style=None): button = Button(self, 10, 10, ??, ??, style is not None ?? style, "Ok") # pass the defaults for w, h, and style if a our style parameter is None else uses the specified style, if the calling code changes the default, our code will automatically use it. button = Button(self, 110, 10, ??, ??, style is not None ?? style, "Cancel") button = Button(self, 110, 10, ??, ??, style is not None ?? style, "Retry", wiindowclass=??) # see keyword "windowclass=??" doesn't make much sense as the result is achieved by excluding it. A similar use case could possibly be made for conditional dict assignments: data = {} if count is not None: data["count"] = count Could be written as data = { "count" = count is not None ?? count, # set the "count" key in the dictionary conditionally, if count is not None, else don't set the key at all "other_param" = ... ?? ..., ... } Thanks, Brian Vanderburg II ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/6O4XDXP2YYS4GRIO3ZDWECUK3IGFWP4R/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-ideas] Experimental syntax proposal
# Experimental Syntax Proposal I would like to propose that Python adopts a modified process before introducing significant changes of its syntax. ## Preamble Given the following file: ```python # coding: experimental-syntax from experimental-syntax import fraction_literal from experimental-syntax import decimal_literal assert 1 /3F == Fraction(1, 3) assert 0.33D == Decimal('0.33') print("simple_test.py ran successfully.") ``` This is what happens when I run it, with the standard Python interpreter: ``` $ python simple_test.py simple_test.py ran successfully. ``` In what follows, I use this as a concrete example for one of the three possible options mentioned. ## The problem Python evolves in many ways including with the addition of new modules in the standard library and with the introduction of new syntax. Before considering the addition of a module in the standard library, it is often suggested to have a version on Pypi so that users can experiment with it, which can lead to significant improvements. However, when it comes to proposed syntax changes, this is currently not possible to do, at least not in any standard way that would immediately be easily recognized as such by the wider community. ## Proposed solutions For those that agree that this is something that could be improved upon, I see at least three possible solutions. 1. Adoption of a simple convention to identify the use of non-standard syntax. This could take the form of a comment with a specific form introduced near the top of the file. This comment could be used as a search term, to identify modules or projects that make use of some custom syntax. 2. Addition of a special encoding module in the Python standard library that can be used to implement nonstandard syntax through source transformation. The short program written at the top provides an example of what this might look like. Note the comment at the top defining a special codec, which could also 3. Addition of a standard import hook in the standard library which could be used, like the special encoding example above, to implement syntactic changes. By doing searches in standard locations (Github, Gitlab, etc.) on, one could identify how many modules are making use of a given experimental syntax, giving an idea of the desirability of incorporating into Python. Imagine how different the discussion about the walrus operator would have been if people had had the opportunity to try it out on their own for a few months prior to a decision being made about adding it to Python. ## New Syntax: two approaches There are currently at least two ways in which one can write a Python program that can use some non standard syntax: * By using an import hook. This is the most powerful approach as it allows one to do changes either at the source level (prior to parsing), or at the AST level, or both. * By using a custom encoding. This only allows transformations at the source level. Both approaches currently require a two-step process. To use an import hook, one has first to load a function that sets up this import hook before importing the module that contains the experimental syntax. This makes it impossible to simply write ``` python module_with_new_syntax.py ``` and have it being executed. Import hooks, like the name implies, only apply to modules being imported - not to the first module executed by Python. With a custom encoding, it is however possible to first register a custom codec either via a site.py or usercustomize.py file. Once this is done, the above way of running a module with new syntax is possible, provided that the appropriate encoding declaration is included in the script. This is what I did with the example shown above. ### Current limitation of these two approaches Using an import hook for enabling new syntax does not work for code entered in the standard Python REPL, which limits the possibility of experimentation. While I have read that specifying the environment variable `PYTHONIOENCODING` enables the Python REPL to use a custom encoding, I have not been able to make it work on Windows and confirm that it is indeed possible to do so. However, I have been able to use a simple customized REPL that can make use of the above. Perhaps the standard REPL could be modified in a similar way. ## New suggested process Assuming one of the options mentioned above is adopted, before changes to the syntax are introduced in a Python version, they would be made available to be used either as an encoding variant or an import hook giving enough time for interested pythonistas to experiment with the new syntax, writing actual code and possibly trying out various alternatives. ## Proof of concept As a proof of concept shown at the beginning of this post, I have created two tiny modules that introduce new syntax that had been discussed many times on this list: 1. a new syntax for decimal literals 2. a new syntax for
[Python-ideas] TextIOWrapper support for null-terminated lines
I have a use case where I'm writing a small filter in Python which should be able to take output from the find command to filter and optionally pass it to other commands (like xargs), but also can be passed specific filenames for the input and/or output. Find can output it's filenames in null-terminated lines since it is possible to have newlines in a filename(yuck). There are workarounds that I can use to get the same thing done, essentially using TextIOWrapper in '' mode and scanning for any null terminators in the lines/splitting manually, but it would be nice if the TextIOWrapper supported null characters as line terminators for such use cases if possible. Something line this: # configure output stream if(arg.input): input_stream = open(arg.input, "rt", newline="\000" if arg.null_lines else None) else: input_stream = sys.stdin input_stream.reconfigure(newline="\000" if arg.null_lines else None) # configure input stream Because my use case also has the ability to specify an encoding for the input/output, my workaround was originally to use codec.getreader/getwriter which turned out to be rather slow (the output of the pipe to the filter was in bursts), so since I'm currently using 3.5 and can't use reconfigure, currently involves detaching sys.stdin and reattaching to a new TextIOWrapper, setting buffering to 0 and newline to '' in null-terminated mode to get all the characters untranslated and manually scanning/splitting on null characters, though I'm sure there are better way to do this. Thanks, Brian Vanderburg II ___ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/BF7IQGAA54TSEBQ4MOC62XK7BSTJE3HO/ Code of Conduct: http://python.org/psf/codeofconduct/