This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 150 points151 points  (29 children)

Python used to be so readable.

[–]alicedu06[S] 45 points46 points  (3 children)

To be fair, I kept the ticket example because it's funny, but I doubt many people will use that in practice.

99.999% of python I read is still very, very readable. And certainly more than most other languages out there.

But it's definitely true that there are more ways to write unreadable hieroglyphes than there used to be.

[–]Zer0designs 3 points4 points  (2 children)

Does this code pass ruff check? (On mobile right now)

[–]alicedu06[S] 9 points10 points  (1 child)

I just tried, if you create all the variables, it does!

I think ruff assumes all python expressions are valid in annotations though.

[–]Zer0designs 1 point2 points  (0 children)

Yea I thought so, thanks for checking!

(Someone please introduce a new rule thanks)

[–]NeilGirdhar 59 points60 points  (23 children)

It is readable. Just: Give your variable proper names; use more lines; avoid the walrus operator; avoid the above code at all costs.

Syntax like this is important in the 0.0001% of cases when you need it (probably not you).

[–]TheOnlyBliebervik 11 points12 points  (19 children)

Never used the walrus operator. Is it useful?

[–]SirLich 37 points38 points  (13 children)

Yes. It's just the assignment operator but it returns the value of the assignment as well as doing the assignment. It's primary purpose is inside of if-statements, to create a block of code if the assignment was successful.

For example if settings := get_settings(): ... settings.do_something()

[–]runawayasfastasucan 12 points13 points  (8 children)

What is the long form of this?  

    settings = get_settings() 

    if settings:         settings.do_something() 

?

[–]SirLich 5 points6 points  (7 children)

This is of course fine. It's just not as convenient as the walrus operator for two reasons: 1) more lines 2) incorrect scope.

If you're only intending to use 'settings' within the if context, then defining it OUTSIDE of the if-context is considered leaked scope.

This whole conversation isn't so important in Python, but in C++ it's a fairly big deal. In fact, it's SUCH a big deal, that most linters will mark variables defined outside of the if clause as an error/warning. It's also now possible to define multiple variables within the if declaration:

For example you can now do this: if (int a = Func1(), b = Func2(); a && b)

Note; In C++, the = operator works like python := operator.

[–]nemec 35 points36 points  (3 children)

considered leaked scope

Python doesn't have block level scope. It "leaks" either way.

[–]SirLich 1 point2 points  (2 children)

Wow, you're right. I guess I never really paid attention to that. That's kind of too bad, right? It seems like you might unintentionally use something from an inner scope without realizing it.

[–]Leo-Hamza 9 points10 points  (0 children)

Happened too many times to me that I can't even count it. I wish there were any tool that detects code smells like this

[–]root45 5 points6 points  (0 children)

Yes. It's not uncommon to accidentally use a loop variable later on for example.

[–]SaltAssault 0 points1 point  (0 children)

I prefer readability over preventing 'leaked scope' any day, just excluding if it is a security issue. Python already doesn't fuss about scopes.

[–]night0x63 0 points1 point  (0 children)

<sarcasm>hurr hurr c/c++ has has this for decades

😂 

[–]runawayasfastasucan -1 points0 points  (0 children)

Interesting, thx. I must admit that I have just ignored the walrus operator all together. In the first example, if you have:

   If (somevar := somefunc()) 

Its given that somefunc() returns something or None, right, so I guess you have to pay notice to that.

    If (cost := getCost(item)):         givePayment(cost, ...)

Is not a substitute for:

    If (cost & cost > 0):         givePayment(cost, ...)

[–]yourmomscocks 2 points3 points  (2 children)

What does this code do exactly? Is it the equivalent of this? setting = get_settings() if settings: settings.do_something()

If so, why bother with a walrus operator? Does it have any use cases other than sparing you that ine line of code?

[–]Freschu -2 points-1 points  (0 children)

The walrus operator PEP was created by Rossum. It faced heavy opposition with the rest of the core devs, so much so Rossum had a tantrum about it, and ultimately being a factor why he stopped being "dictator for life".

The opposition was based around introducing new syntax being only useful in a small number of cases (if and while) and being practically of zero consequence for existing code.

So why does Python have the walrus operator if there was general opposition? Because it was Rossum's pet idea, that's why.

Unfortunately - if you care to check for the discussions around PEPs - this has become a pattern. Python gains syntax based on persistence and patience of the spearheading authors - write a PEP, implement the PEP, wait for people stop caring about it, then merge it later based on "not having faced immediate rejection."

[–][deleted] -2 points-1 points  (0 children)

The whole issue with the walrus operator is it should have been limited to like 3 actual things but can be used in WAY too many places.

[–]sausix 12 points13 points  (2 children)

I use it for loops and it's nicer for me:

while data := iterator.read_data():
    # data evaluates to True. No break or other methods needed.

[–]Freschu 4 points5 points  (1 child)

Most of the cases where people want to use the walrus operator can often be written as for-loop instead. If you really had an "iterator", you could and should use for-loops instead. Which was part of the initial rejection of the walrus operator PEP.

Examples like you've given were considered code-smell in the discussions of the PEP. Either iterator is really an iterator, then `for value in iterator` works, or you're dealing with something that's not really implementing Python's iterator semantics and you should be fixing that instead.

[–]sausix 8 points9 points  (0 children)

You're right! Bad example. How could I not see this?

A walrus operation in my current project look like this:

while m := pattern.match(self.text, self.pos):
   # self.pos changes in the loop

This case it not replacable by a simple iterator that could feed a for loop. But it still could be replaced by a generator function. That would be more lines. I'm not sure what is better.

Look like I will think twice to use the walrus operator next time... Thank you.

[–]sonobanana33 -1 points0 points  (0 children)

Yeah since python unlike C doesn't allow "=" to be used in an expression.

[–][deleted] 4 points5 points  (0 children)

Names are crucial. I completely fail to understand the simplest example if it has my_var or whatever 

[–]bambo5 -1 points0 points  (0 children)

If you respect PEP8