DEV Community

Cover image for 11 Tips And Tricks To Write Better Python Code

11 Tips And Tricks To Write Better Python Code

Patrick Loeber on July 28, 2020

You can read the original article on my website: https://www.python-engineer.com/posts/11-tips-to-write-better-python-code/ In this tutorial I...
Collapse
 
andrewharpin profile image
Andrew Harpin

I fundamentally disagree with 1, unless there is a performance benefit or some other benefit not covered by your simplistic example.

For a non-python coder or inexperienced python coder, your initial example is much more readable. It is obvious what is happening.

Someone unfamiliar with enumerate needs to learn what it does, what the parameter order is and then apply that understanding to the code below, with the first this is not required.

Additionally, the enumerate is potentially subject to errors as operator precedence is critical to its operation.

For 2, I have a passionate hatred of nested for or if operations, there are occasions where they are necessary, but these are generally quite rare.

As you mention, they affect code readability, but they also affect maintainability of the code, when the addition or change of functionality can become difficult.

A lot of people use them too frequently on the premise of code compaction, but this is just a cover for poor design, where better abstraction would be more beneficial.

Collapse
 
vedgar profile image
Vedran Čačić

First, please read python.org/dev/peps/pep-0279/. Python design is (or at least it was at the time enumerate was introduced) itself a well-designed community-driven peer-reviewed process. Somebody thought about all your objections and addressed them in a way that was deemed satisfactory by BDFL. Also see nedbatchelder.com/text/iter.html. There is more to loops than C-style "compare, add, dereference, increment" low-level twiddling.

Second, your other objections are just FUD. Parameter order? There is only one parameter. Yes, there is an optional one, but the usual convention (not only in Python) is that the optional parameter always follows the mandatory one. [It's incredibly ironic that the builtin you defend as completely obvious, range, is one of very rare exceptions to that rule.] And what does operator precedence do there? There are no operators at all in the usual use of enumerate.

Collapse
 
pat_loeber profile image
Patrick Loeber • Edited

Thanks for the extensive feedback!
Agree with 2, a lot of people use them too frequently and we should be careful here.

I also agree that range(len()) is fine and might be better suited for a beginner. I would never teach a beginner this method the first time I'm showing the for-loop. But as I said in the beginning, I wanted to show how the code can be more elegant and Pythonic. I'm not sure if better readability always has to mean that the code should be suited for a complete beginner. And the enumerate function shouldn't be too hard to understand once someone learned about it.

Collapse
 
andrewharpin profile image
Andrew Harpin

I disagree that it is more elegant, my personal opinion is good code can be read by a non coder, at least from an overview perspective.

With the other solution they would struggle as it requires inside knowledge, whereas range and len are much more obvious.

Thread Thread
 
aezore profile image
Jose Rodriguez

I also prefer enumerate anytime. range(len()) seems to defeat the motto of “simple over complex”. enumerate seems quite descriptive to me (non-English speaker) and otherwise once explained falls flat. If you are concern about variable unpacking...it makes sense to iterate over an index if you come from C, but python “for-each” approach seems to me more readable. IMHO ❤️

Collapse
 
vedgar profile image
Vedran Čačić

3) Use the batteries, Luke. from operator import attrgetter.

5) Don't use sys.getsizeof unless you know a lot more about Python's memory model. nedbatchelder.com/blog/202002/sysg...

7) (This should be a separate item, it's incredibly important for writing Pythonic code) Unpack, don't index. In the same way as enumerate is better than range with subscripting, also here. [(top, _)] = counter.most_common(1). Much easier to read than that [0][0] sorcery.

10) Better yet, use a dedicated operator instead of relying on implementation detail. python.org/dev/peps/pep-0584/

11) should use 4) :-P. colors is really a set, right? Not only is is semantically better, it's also asymptotically much faster to search.

Collapse
 
pat_loeber profile image
Patrick Loeber

Awesome feedback, thanks! Totally agree on those points. I have to admit I did not know about this sys.getsizeof issue...and yes, colors should be a set ;) I just wanted to show a dummy example...

Collapse
 
vedgar profile image
Vedran Čačić • Edited

Yeah, that's your main problem: your examples are a bit too dummy. :-) But it is so when you take the design that's important for real-life applications and try to justify it with 5 lines of code. :-]

The problem is not with getsizeof. It does the best job it can, given the memory model. The problem is that Python's objects are not boxes of well-defined edges. The question, strictly speaking, doesn't have a meaningful answer. If I say a.t = b.t = x, should x count towards the size of a or b? Or both? Or neither? :-)

(If only one: the memory is the same as after b.t = a.t = x, so it should be symmetric.
If both: there is only one x in memory. After c.t = x, the memory usage doesn't go up by size of x.
If neither: well, then almost nothing uses any memory: objects just refer to other objects, not "contain" them.)

Thread Thread
 
pat_loeber profile image
Patrick Loeber

thanks for the explanation :)

Collapse
 
kovah profile image
Kevin Woblick

Excellent tips for Python beginners like me. Clean and precise descriptions and no blah blah. Thank you very much!

Collapse
 
pat_loeber profile image
Patrick Loeber

Thanks a lot for the feedback :)

Collapse
 
jingxue profile image
Jing Xue

11) why not make colors a set?

Collapse
 
pat_loeber profile image
Patrick Loeber

Good point! Probably a set would be even better to store the colors here. I just wanted to show a dummy example, and in "real life" code a lot of times you stumble on situations where you have a list that you want to check...

Collapse
 
jingxue profile image
Jing Xue

Understood. Actually come to think of it, when you have only a few items, a list is not necessarily slower and definitely more memory efficient than a set. :-)

Collapse
 
ravikeshare profile image
Ravi

Nice Article, thanks for sharing it.

Collapse
 
amirdarx profile image
amir

wooow really Tnx , very complete and helpful topics

Collapse
 
pat_loeber profile image
Patrick Loeber

Glad you like it :)

Collapse
 
bawbam profile image
Ivan López

thank you so much, excellent post for beginners :)

Collapse
 
pat_loeber profile image
Patrick Loeber

Thanks for the feedback!

Collapse
 
banji220 profile image
Banji

Boom!
That's what we need these days
Tnx for sharing
Happy coding with ❤️

Collapse
 
pat_loeber profile image
Patrick Loeber

Thanks for reading :)

Collapse
 
junaid_mahmud profile image
Junaid Mahmud

Thank you very much for this. It helped me to have a clearer idea.

Collapse
 
pat_loeber profile image
Patrick Loeber

Glad you like it!