📜 ⬆️ ⬇️

Code Like a Pythonista: Idiomatic Python (part0)

Kaa, the Python
From the translator :

I just started learning Python. From the very first acquaintance, the language pleased us with nice constructions and a syntactically guaranteed convenience for reading and understanding the code.
In the process of mastering, while writing my own code, I sometimes doubt the correctness of the chosen methods from the point of view of the Python-way ( PEP 8 - Style Guide for Python Code , if you like). To understand the ideology of programming, in the Python-community, in addition to comprehensive documentation, to everyone's joy, a lot of supporting materials have been accumulated, such as the article Python Tips, Tricks, and Hacks , whose translation recently appeared on Habré
I liked David Guder’s article “Write code like a real Pythonist: Python idiomatics” ( David Goodger “Code Like a Pythonista: Idiomatic Python” ). For better assimilation, I decided to issue (by virtue of skill) a full-fledged translation, then it seemed like a sensible idea to share with Habr.
While I was working on the translation, it came to be understood that the article is much larger than it seemed when reading it in the original, so I will post in parts so as not to fall out of the format of the Habra article.
Continuation and completion of the translation.




')

Write the code like a real Pythonist: Python idiomatics


David Goodger
goodger@python.org
http://python.net/~goodger

In this interactive tutorial, we will look at many essential Python idioms and advanced-level techniques that will certainly expand your toolkit.
There are three versions of this presentation:

Creative commons
Attribution / Share-Alike (BY-SA) license.
About me:

I presented this tutorial at the PyCon 2006 conference (called Text & Data Processing), I was surprised by the reaction to some of the methods that I used and considered them well-known. But many listeners were ignorant of the methods used by Python programmers without thinking.
Many of you may have seen some idioms and methods before. I want to believe that you will also learn a few tricks that you have not seen before and maybe you will learn something new about those that you already know.


Zen Python (1)


These are the basic principles of Python, but in an extended interpretation. A sense of humor is simply necessary for their proper understanding.
If you use a programming language named after the comedy sketch troupe, it’s best to have a sense of humor.

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complicated.
The complex is better than confusing.
Flat is better than nested.
Sparse is better than dense.
Readability is important.
Exceptional cases are not exclusive enough to break the rules.
Although practicality is more important than beauty.
Errors should not pass silently.
Unless explicitly drowned.
...


Zen Python (2)


With ambiguity, resist the temptation to guess.
There must be one, and preferably only one, obvious way to do this.
Although this path may not be obvious at first, unless you are from Holland (apparently meaning Guido van Rossum - approx. Transl., Thanks sgtpep ).
Now is better than never.
Although never often better than right now .
If the implementation is difficult to explain, then this is a bad idea.
If the implementation is easy to explain, this is probably a good idea.
Namespaces are a great idea, so let's make even more namespaces!

—Tim Peters
This “poem” was created as a joke, but in reality it contains many truths about the Python philosophy.
For a long time Pythoneer Tim Peters shifted the principles of the BDFL manual into 20 brief aphorisms, only 19 of which were recorded.
http://www.python.org/dev/peps/pep-0020/

You can decide for yourself who you are: “Pythoneer” or “Pythonista”. These words have associated meanings.

When in doubt:
import this <br/>

Try this in an interactive Python interpreter:
>>> import this <br/>

Here is another Easter egg:
>>> from __future__ import braces<br/>
File "<stdin></stdin>" , line 1 <br/>
SyntaxError : not a chance<br/>

What a bunch of comedians! :-)


Coding style: readability is important (Coding Style: Readability Counts)


Programs must be written for people to read and only by chance for the machine to execute.
—Abelson & Sussman, Structure and Interpretation of Computer Programs (“Structure and Interpretation of Computer Programs”)

Try to make your programs easy to read and obvious.

PEP 8: Python Code Style Guide


It is worth reading:
http://www.python.org/dev/peps/pep-0008/

PEP = Python Enhancement Proposal (Python Development Suggestions)
PEP is a document representing information to the Python-community, describing new features of Python, its processes or environment.
The Python community has its own standards that describe how the source code should look, set out in PEP 8. These standards differ from others, such as C, C ++, C #, Java, VisualBasic, etc.
Because indents and spaces are extremely important in Python, the Style Guide for Python code uses standard indents. It is wise that the management adheres to the manual! .. Most of the open-source projects and (hopefully) home projects, too, follow the guidelines quite strictly.


Spaces 1




Spaces 2



def make_squares (key, value = 0‌ ):<br/>
"""Return a dictionary and a list...""" <br/>
d = {key: value}<br/>
l = [key, value]<br/>
return d, l<br/>


Naming




Long lines of code (Lines) and their continuation


Keep lines of code within 80 characters.
Use implicit line continuations inside brackets:
def __init__ ( self , first, second, third,<br/>
fourth, fifth, sixth):<br/>
output = (first + second + third<br/>
+ fourth + fifth + sixth)<br/>

Use backslash:
VeryLong . left_hand_side \<br/>
= even_longer . right_hand_side()<br/>

Beksleshi use caution; they must complete the line in which they are included. If you add a space after backslash, it will no longer work. Thus, this somewhat pollutes the code.

Long strings


The adjacent literal strings (characters) are concatenated by the parser:
>>> print 'o' 'n' "e" <br/>
one<br/>

Spaces between the letters are not required, but they help to make the code more readable. Any type of quotes can be used:
>>> print 't' r'\/\/' """o""" <br/>
t\ / \ / o<br/>

Lines beginning with “r” are “raw”. Backsleshs are not considered escapes in raw lines. They are used for regular expressions and paths in Windows file systems.
Note that named string objects are not concatenated:
>>> a = 'three' <br/>
>>> b = 'four' <br/>
>>> a b<br/>
File "<stdin>" , line 1 <br/>
a b<br/>
^ <br/>
SyntaxError : invalid syntax<br/>

This is because automatic concatenation is a feature of the Python parser (parser), and not the interpreter. You must use the "+" operator to combine strings in runtime.

text = ( 'Long strings can be made up ' <br/>
'of several shorter strings.' )<br/>

Parentheses allow implicit concatenation of lines of code.
To specify multi-line string values, use triple quotes:

"""Triple<br/>
double<br/>
quotes"""
<br/>

'''\<br/>
Triple<br/>
single<br/>
quotes\<br/>
'''
<br/>

In the last example (single quotation marks), notice how backslash is used to avoid the terminating character. This eliminates unnecessary characters at the end of the line when storing text and quotes aligned to the left margin. Backslesh should be at the end of each such line.


Compound Operators



Good:
if foo == 'blah' :<br/>
do_something()<br/>
do_one()<br/>
do_two()<br/>
do_three()<br/>

Poorly:
if foo == 'blah' : do_something()<br/>
do_one(); do_two(); do_three()<br/>

Spaces and indents are useful visual indicators of the program flow. The indentation of the second line of the “Good” code above shows the reader the fulfillment of something according to the condition, while the lack of indentation in the “Bad” hides the “if” condition.
A lot of operators on one line of code is the main sin. In Python, readability is important .



Documentation lines and comments



Documentation lines = How to use code

Comments = Why (reasonable justification) and how the code works
The documentation lines explain how to use the code, and for users of your code. Using docstrings:

Comments explain why and are needed for the minters of your code. Examples include notes for yourself like:
# !!! BUG: ... <br/>
<br/>
# !!! FIX: This is a hack <br/>
<br/>
# ??? Why is this here? <br/>

Both of these groups include you , so write good documentation lines and comments!
Documentation lines are used online (help ()) and for auto-documentation systems.

False comments and documentation lines are worse than nothing at all. So save them right away! When you make changes, make sure that the comments and lines of documentation match the code and do not contradict it.
The PEP has a whole agreement about the documentation strings, PEP 257, “Docstring Conventions”:
http://www.python.org/dev/peps/pep-0257/



Practicality wins purity



Foolish consistency is a little monster of the distant mind (A foolish consistency is the hobgoblin of little minds).
—Ralph Waldo Emerson

( hobgoblin : Something superstitious fear)
(Note. Trans.: As I understand it, the meaning is: “Teach a fool God to pray - he will hurt his forehead”)
There are always exceptions. From PEP 8:
It is very important when a contradiction arises - it happens that following the leadership is simply not acceptable. When in doubt, use the solution that is best for you. Look at other examples and decide which point is better. And do not hesitate to ask!
Two good reasons to break accepted rules:
  1. When you follow the rules, the code becomes less readable, even for someone who is used to following the rules.
  2. To comply with the surrounding code, it is also possible to break (this may be for historical reasons) - although this may be an opportunity to bring order to someone's confusion (in the Tru-XP style (eXtreme Programming - note note transl.)).



... but practicality should not break the purity all the time!

Potpourri of idioms


A selection of small, useful idioms.
Now we come to the main part of the tutorial: a lot of idioms.
We will start with those that are easier and gradually raise the level.



Value exchange


In other languages:
temp = a<br/>
a = b<br/>
b = temp<br/>

In Python:
b, a = a, b<br/>

You may have seen it before. But do you know how it works?


The right side is unpacked by name into the tuple on the left side.
More unpacking examples:
>>> l = [ 'David' , 'Pythonista' , '+1-514-555-1234' ]<br/>
>>> name, title, phone = l<br/>
>>> name<br/>
'David' <br/>
>>> title<br/>
'Pythonista' <br/>
>>> phone<br/>
'+1-514-555-1234' <br/>

Useful in cycles for handling structured data:

Above we have created a list (David's info). people - a list of people containing two items, each of which is a list of three items.
>>> people = [l, [ 'Guido' , 'BDFL' , 'unlisted' ]]<br/>
>>> for (name, title, phone) in people:<br/>
... print name, phone<br/>
... <br/>
David + 1 - 514 - 555 - 1234 <br/>
Guido unlisted<br/>

Each people element was unpacked into a view tuple (name, title, phone).
Just do not forget to match the structure on the left and right!
>>> david, (gname, gtitle, gphone) = people<br/>
>>> gname<br/>
'Guido' <br/>
>>> gtitle<br/>
'BDFL' <br/>
>>> gphone<br/>
'unlisted' <br/>
>>> david<br/>
[ 'David' , 'Pythonista' , '+1-514-555-1234' ]<br/>



More about tuples


We saw a comma being the designer of a tuple, without parentheses. Example:
>>> 1 ,<br/>
( 1 ,)<br/>

The Python interpreter shows brackets for clarity, and I recommend that you also use them:

>>> ( 1 ,)<br/>
( 1 ,)<br/>

Do not forget the comma!
>>> ( 1 )<br/>
1 <br/>

In a single element tuple, a final comma is required; in 2 + tuples, the final comma is optional. In 0-tuples, or empty tuples, a pair of parentheses is a shortened syntax:
>>> ()<br/>
()<br/>

>>> tuple ()<br/>
()<br/>

A common typo is to leave a comma in the code, even if you do not want to create a tuple. You can easily skip it in your code:
>>> value = 1 ,<br/>
>>> value<br/>
( 1 ,)<br/>

Thus, if you see a tuple where you did not wait, look for a comma!


Interactive "_"



This is a really useful feature, surprisingly, few people know about it.

In the interactive interpreter mode, whenever you try an expression or a function call, the result is stored in a temporary variable, _ (underscore):

>>> 1 + 1 <br/>
2 <br/>
>>> _<br/>
2 <br/>

_ stores the last print statement printed. It's comfortable!
But it works only in the interactive mode of the interpreter, not in the modules.

Especially useful when you are working on a task online and want to save the result for the next step:

>>> import math <br/>
>>> math . pi / 3 <br/>
1.0471975511965976 <br/>
>>> angle = _<br/>
>>> math . cos(angle)<br/>
0.50000000000000011 <br/>
>>> _<br/>
0.50000000000000011 <br/>



Composing strings from substrings


Let's start with a list of lines:
colors = [ 'red' , 'blue' , 'green' , 'yellow' ]<br/>

We want to merge all the lines together into one big line. Especially when the substrings are many ...

do not do this:
result = '' <br/>
for s in colors:<br/>
result += s<br/>

This is very inefficient.

It horribly eats up memory and degrades performance. Summation calculates, stores, and then destroys an object at each intermediate step.


Instead, do this:
result = '' . join(colors)<br/>

The join () string method makes all copies in one pass.
When you are dealing with a pair of dozens or hundreds of lines, this will not make a noticeable difference. But get used to collecting lines effectively, because it will give a gain with thousands of lines and when working in cycles.



String composition, variation 1


Here are some ways to use the join () method.

If you want to put spaces between your substrings:
result = ' ' . join(colors)<br/>

Or commas and spaces:
result = ', ' . join(colors)<br/>

In general:
colors = [ 'red' , 'blue' , 'green' , 'yellow' ]<br/>
print 'Choose' , ', ' . join(colors[: - 1 ]), \<br/>
'or' , colors[ - 1 ]<br/>

To make up a grammatically correct sentence, we want to put a comma between all the values, and before the last word "or". Here helps slice syntax. “Slice to -1” ([: -1]) gives the index of the penultimate element which we will add, separated by commas with a space.
Of course, this code does not want to work in cases where the length of the list is 0 or 1.

Conclusion:
Choose red, blue, green or yellow<br/>


String composition, variation 2


If you need to apply a function to generate substrings:
result = '' . join(fn(i) for i in items)<br/>

It uses a generator expression , which we will discuss later.

If you need to calculate the substrings step by step, first collect them into the list:
items = []<br/>
... <br/>
items . append(item) # many times <br/>
... <br/>
# items is now complete <br/>
result = '' . join(fn(i) for i in items)<br/>

We assembled the parts into a list so that we can now apply the string method join
for greater efficiency.





The second part of the translation



Source: https://habr.com/ru/post/88972/


All Articles