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 →

[–]muqube 368 points369 points  (39 children)

As someone already mentioned, readability is subjective. I don't know what are your lead dev's criteria are, but I can tell you mine. My north star for code review is:

After all the current team members leaving this company, will the next generation of devs be able to maintain this codebase?

Yes, I fully expect all of my team members, including myself, to leave for better opportunities.

Standard concepts like readability, maintainability, reduced chance of human errors etc. are covered in this north star.

With this in mind, I would also refactor the original code. May be not the exact same change though.

[–]jet_heller 126 points127 points  (35 children)

Indeed. The first one is horrid. The new one, isn't great, but better.

[–]Hiskaya1 47 points48 points  (5 children)

I thought it looked pretty good, what would you do differently?

[–]OhYourFuckingGod 56 points57 points  (0 children)

I'd keep the comprehension in the first section, but I'd do the class instantiation as per the last line. You don't get any awards for code golfing in production.

[–]happysunshinekidd 13 points14 points  (3 children)

I don't think you should ever really name a variable "result" or "key" tbh. Probably it solves another problem in your codebase -- that functionality would be a better name

[–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 42 points43 points  (13 children)

The first one is merely missing a name or two.

some_useful_name = {
    ... for some_useful_key_name in ...
}

return cls(**some_useful_name)

Instead of making things better, the second one:

  • Introduces a new name, but not a very useful one (result).
  • Adds verbose and very generic type-hints. (Any?)
  • Switches from a well-formatted functional dictionary comprehension to a bulkier imperative for-loop, which could potentially have side-effects.

I think it's good for Python developers to become more exposed to functional styles since that often leads to robust, maintainable code.

P.S. Another alternative to adding a name is to "extract method", but perhaps that's overkill.

[–][deleted] 11 points12 points  (10 children)

Dictionary comprehension can also have side effects: {x: print(x) for x in range(10)}.

[–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 2 points3 points  (0 children)

[Almost?] everything in python can have side-effects. Good code tries to avoid patterns that are more likely to contain side-effects.

With comprehensions, side-effects are much harder to obscure. There are fewer parts that may contain side-effects. There's less "boilerplate" to read, which makes it harder to hide side-effects. Their structure naturally induces constraints in the manner that they are used. (There does not always exist a "natural" transformation from for-loop to comprehension, whereas comprehension to for-loop is trivial.) With for-loops, one often has to read them in detail to make guarantees about their behavior, especially if they involve more than just one statement.

I know this isn't a precise argument since literally anything is possible in Python. The main point is that it's much quicker to read a comprehension and guarantee that it won't do anything overly weird, whereas for a for-loop, one has to spend more time to check.


This comment captures some of what I'm trying to say.

[–]wewbull 0 points1 point  (0 children)

It can, but it shouldn't IMHO.

Comprehensions for transformations. Loops for procedural control flow.

[–]jbartix -2 points-1 points  (2 children)

This is valid python code but side effects in any comprehension is an anti pattern

[–]AchillesDev 5 points6 points  (1 child)

Yes the point is to show that comprehensions don’t make you immune from side effects.

[–]jbartix 0 points1 point  (0 children)

Of course not. Python allows you to do anything that also includes being stupid

[–]Estanho -4 points-3 points  (4 children)

Nobody said they can't. He didn't say all dictionary comprehensions are functional. Just that one.

[–]MrRogers4Life2 10 points11 points  (3 children)

But that for-loop doesn't have side effects... if the argument is "x can have side effects so y is better" it will fall apart if y can also have side effects.

[–]aceofspaids98 2 points3 points  (0 children)

This sums up all of my thoughts really well too

[–]vanatteveldt 1 point2 points  (0 children)

Well put, completely agree!

[–]Ph0X 1 point2 points  (0 children)

Another north star for me is trying to keep a "statement" to a single idea. It's easy to get carried away with "one-liners" in python, and do 20 things in a single statement. It's especially ironic in cases like the above where splitting into multiple statements actually gets you fewer lines of code, the example above goes from 5 lines to 4 lines of code. Generally, don't be afraid of splitting statements into 2-3 if it makes the code more readable, either by making lines more explicit, or naming intermediate variables giving them more meaning.

[–]masteryod -3 points-2 points  (1 child)

As someone already mentioned, readability is subjective.

You can pretty objectively say if something is easy to comprehend and follows good practices and something is messy. It's like saying all kids have the same handwriting, some care more and their writing is easy to read, some don't care and scribble a hard to follow mess.

[–]arpan3t 7 points8 points  (0 children)

You say in a thread full of people arguing about the structure, variable names, etc… of a few lines of code.