Live data from Hacker News

What’s New in Python 3.8

docs.python.org

361–370 of 381 posts

Re: What’s New in Python 3.8

#361

Earlier quoted context omitted.

Coming from Perl, I used to want this badly, but then I thought that there's absolutely nothing wrong with m = re.match(...) if m is not None: pass Now, I wonder what you meant saying that single-line version is less error-prone, because I don't think so. I believe they're exactly the same in this regard, except for a bizarre case when someone would bastardize the code by putting some irrelevant lines between the ass…

Think about if you match multiple patterns: for line in f: if (m:= pat1.search(line)) is not None: ... do stuff .. elif (m:= pat2.search(line)) is not None: ... do other stuff .. elif (m:= pat3.search(line)) is not None: ... do something else .. In older Python that's: for line in f: m = pat1.search(line) if m is not None: ... do stuff .. else: m = pat2.search(line) if m is not None: ... do other stuff .. else: m = p…

If actions are different, I tend to put them in functions (independent testable pieces, yay!) and iterate over a mapping:

    LINE_ACTIONS = (
        (re.compile("pattern 1"), do_stuff),
        (re.compile("pattern 2"), do_other_stuff),
        (re.compile("pattern 3"), do_something_else),
    )
    ...
    for pattern, action in LINE_ACTIONS:
        m = pattern.search(line)
        if m is not None:
            action(m)
            break
Or even use a method registry pattern that would auto-populate LINE_ACTIONS by just declaring the fuctions:

    @action("pattern 1")
    def do_stuff(m):
       ...
Alternatively, I might just break the processing into a function:

    def _process(line):
        m = pat1.search(line)
        if m is not None:
            ... do stuff ...
            return

        m = pat2.search(line)
        if m is not None:
            ... do stuff ...
            return

        m = pat3.search(line)
        if m is not None:
            ... do stuff ...
            return

    _process(line)
Of course, this depends on the purpose. Could be completely inadequate in some situations.

Re: What’s New in Python 3.8

#362

Earlier quoted context omitted.

Because of the luddites at RedHat, Python2.7 isn't actually dead until 2024. It's infuriating. https://access.redhat.com/solutions/4455511

If you want other people to make a change then it's on you to make a convincing argument for why the new thing is an improvement, not just go on tirades about how people should get with the times. Personally, I lost faith in the Python core team because of the Py3 migration. Yes, 3.x now has a bunch of nice features that 2.x did, but almost none of them actually depend on the 3.0's breakage (as proven by Tauthon). If…

> If you want people to follow you through a break-the-world migration then you need to motivate why it is needed and why it couldn't be done incrementally

They did. I remember looking through this, and I remain convinced that the core developers were correct and there was no way to fix Unicode handling incrementally.

Re: What’s New in Python 3.8

#363
post #22

As a developer who has primarily developed applications in Python for his entire professional career, I can't say I'm especially excited about any of the "headlining" features of 3.8. The "walrus operator" will occasionally be useful, but I doubt I will find many effective uses for it. Same with the forced positional/keyword arguments and the "self-documenting" f-string expressions. Even when they have a use, it's us…

The audit hooks are going to allow some really interesting things, especially around security controls on executing Python code. There is hope for sandboxed Python execution!

Re: What’s New in Python 3.8

#364
post #112

Earlier quoted context omitted.

IMHO the whole `re.match` is a design flaw in stdlib. re.match() should always return a match object, but instead .group(1) will return None. Then we can write one-liners easier without the walrus operator.

I think you mean .group(0) as .group(1) can already return None: >>> import re >>> pat = re.compile("(A+)|(B+)") >>> m = pat.search("HUBBLE") >>> m.group(1) is None True >>> m.group(2) 'BB' >>> m.group(0) 'BB' I don't see how using your proposed change would help.

I mean re.search() should always return a MatchObject, dont return None.

Re: What’s New in Python 3.8

#365
post #314

Earlier quoted context omitted.

Well the zen of python also states: - Complex is better than complicated. Using the walrus operator makes the code more complex, but less complicated.

It also states one line before: > Simple is better than complex. I understand that nobody will force me to use this feature, but as I said before, even the spec and the write up tells how this feature is confusing and .. complex.

> It also states one line before

I know and I believe there is a purpose to be exactly after that line. Writing only simple code is not enough. If you write everything in a simple manner your code will most likely be complicated, that's exactly why you have next - complex is better than complicated.

I see this feature the same way as comprehensions, scary and complex at first, but once you learn it you would wish anyone would use it.

Re: What’s New in Python 3.8

#366
post #210

Earlier quoted context omitted.

I think there are a lot of use-cases for some kind of dedicated "if-with-outputs" syntax, where you have some extra variables available inside the if-block if the condition matched. Such a syntax could cover a lot of the problems of double execution but also prevent hard to understand code like the walrus operator. ... I've got no idea how the syntax could look though.

How would this hypothetical syntax differ from the walrus operator? I.e. what is hard to understand with the walrus operator that wouldn't be with this new hypothetical syntax and why?

I think it could avoid cases where you "abuse" the walrus operator and make code harder to understand than necessary. E.g. things like:

  if (value := func()) and another_condition:
    ...
Or:

  if another_condition or (value := func()):
    ...
Or:

  x=1
  my_list = [x := x+1, x := x-1]
etc.

Re: What’s New in Python 3.8

#367

Earlier quoted context omitted.

If you want other people to make a change then it's on you to make a convincing argument for why the new thing is an improvement, not just go on tirades about how people should get with the times. Personally, I lost faith in the Python core team because of the Py3 migration. Yes, 3.x now has a bunch of nice features that 2.x did, but almost none of them actually depend on the 3.0's breakage (as proven by Tauthon). If…

> If you want people to follow you through a break-the-world migration then you need to motivate why it is needed and why it couldn't be done incrementally They did. I remember looking through this, and I remain convinced that the core developers were correct and there was no way to fix Unicode handling incrementally.

Add the u-sigil for unicode (as they did), add the b-sigil for bytestrings (as they eventually did), and then go through a regular deprecation cycle for sigil-less strings (rather than releasing a 3.0 where the u-sigils were removed completely). Maybe at some point re-add sigil-less strings as an alias for u-strings, but I'd rather have old stuff break with a clear message than have a bunch of weird side bugs.

Do the same for the type names.

Re: What’s New in Python 3.8

#368

Earlier quoted context omitted.

Think about if you match multiple patterns: for line in f: if (m:= pat1.search(line)) is not None: ... do stuff .. elif (m:= pat2.search(line)) is not None: ... do other stuff .. elif (m:= pat3.search(line)) is not None: ... do something else .. In older Python that's: for line in f: m = pat1.search(line) if m is not None: ... do stuff .. else: m = pat2.search(line) if m is not None: ... do other stuff .. else: m = p…

If actions are different, I tend to put them in functions (independent testable pieces, yay!) and iterate over a mapping: LINE_ACTIONS = ( (re.compile("pattern 1"), do_stuff), (re.compile("pattern 2"), do_other_stuff), (re.compile("pattern 3"), do_something_else), ) ... for pattern, action in LINE_ACTIONS: m = pattern.search(line) if m is not None: action(m) break Or even use a method registry pattern that would auto…

Indeed, I've also used this pattern.

I've found that I don't like using it. As you write, it's "inadequate in some situations", which I consider as part of the cumbersome complexities I mentioned.

For examples, do_stuff() and do_other_stuff() may need to share variables, and do_something_else() might need the line number to report an error while the others don't.

This can be handled with shared state/nonlocal, and by passing in more parameters to the generic handler API, but these add complexity.

Or, different parts of the file may have different line dispatch processing (eg, a header block followed by a data block followed by a footer block) where one of the handlers must indicate the transition to a different processor.

Also, function dispatch in CPython is slow. While the regex tests are also slow, it can also be important to consider the (using a hypothetical number) 5% overhead for dispatching over inline code.

Re: What’s New in Python 3.8

#369
post #22

As a developer who has primarily developed applications in Python for his entire professional career, I can't say I'm especially excited about any of the "headlining" features of 3.8. The "walrus operator" will occasionally be useful, but I doubt I will find many effective uses for it. Same with the forced positional/keyword arguments and the "self-documenting" f-string expressions. Even when they have a use, it's us…

> As a developer who has primarily developed applications in Python for his entire professional career, I can't say I'm especially excited about any of the "headlining" features of 3.8. Python is a fairly old, mature language. What features would you have been especially excited about?

I want to build executables that I can pass around without also sending an entire environment. Crazy that’s not a native feature.

Re: What’s New in Python 3.8

#370
post #366

Earlier quoted context omitted.

How would this hypothetical syntax differ from the walrus operator? I.e. what is hard to understand with the walrus operator that wouldn't be with this new hypothetical syntax and why?

I think it could avoid cases where you "abuse" the walrus operator and make code harder to understand than necessary. E.g. things like: if (value := func()) and another_condition: ... Or: if another_condition or (value := func()): ... Or: x=1 my_list = [x := x+1, x := x-1] etc.

Ah ok, so you'd essentially allow it in fewer contexts? I would definitely have supported that, although I do think combining walrus with other boolean expressions in if and while is super useful and not particularly hard to understand.
Post reply on HN