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 Goodgergoodger@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 live in Montreal,
- father of two children, husband of one woman
- Python programmer full-time (a full-time Python programmer),
- author of the project Docutils and reStructuredText ,
- Python Enhancement Proposals editor (or PEPs),
- the organizer of PyCon 2007, and the PyCon 2008 department,
- member of the Python Software Foundation
- the director of the foundation last year, and the secretary this year.
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
- 4 spaces on one indent level.
- No tabulations.
- Never mix tabs and spaces.
This is exactly supported in IDLE and Emacs Python mode. Other editors can do this too.
- One blank line between functions.
- Two blank lines between classes.
Spaces 2
- Add a space after "," in dictionaries, lists, tuples, argument lists, and after ":" in dictionaries, but not before.
- Insert spaces around assignments and comparisons (except argument lists).
- There are no spaces inside the parentheses or in front of the argument list.
- No spaces at the beginning and end of the documentation lines.
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
- single-line for functions, methods, attributes
- joined_lower or ALL_CAPSA for constants
- StudlyCaps for classes
- camelCase only to comply with predefined agreements
- Attributes: interface, _internal, __private
Try to avoid the __private form. I never use it. Believe me. If you use it, you will regret it later.
Explanation:
People who came after C ++ / Java are prone to the improper and excessive use of this “feature”. __private names do not work as they do in Java or C ++. It simply "starts" the name conversion mechanism (name mangling) , which helps prevent accidental collisions of namespaces in subclasses: MyClass .__ private becomes MyClass._MyClass__private. (Note that this works even for subclasses with the same name as the superclass, for example, a subclass defined in another module.) Thus, it is possible to access __private names outside the class, but it is inconvenient and fragile (this adds to the dependence on the exact name superclass).
The problem is that the author of the class can naturally think: “This attribute / method name should be private, accessible only within this class definition” and use the __private declaration. But later, a user of this class can create a subclass in which he legitimately needs access to this name. For this, the superclass can be changed (which can be difficult or impossible), or in the code of the subclass to apply name conversion (mangled names) (which is ugly and fragile at best).
This is the concept of Python: "We are all adults here."
If you use the __private form, from whom are you protecting the attribute? It is the responsibility of the subclasses to use the attributes of the superclass correctly, and the responsibility of the superclass is to document their attributes correctly.
For these purposes, it is better to use an ad starting with a single underscore, _internal. It does not translate names; simply telling others “to be more careful with this is the realization of internal mechanisms; Do not touch it if you do not fully understand it. " Yet this is only an agreement.
There are some good explanations in the answers here:
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 worksThe documentation lines explain
how to use the code, and for
users of your code. Using docstrings:
- Explain the purpose of the function, even if it seems obvious to you, because it may not be obvious to anyone later.
- Describe the expected parameters, return values, and any exceptions thrown.
- If the method is tightly coupled to a single call, create some connection with the caller (although be careful, because the caller may change afterwards).
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:
- When you follow the rules, the code becomes less readable, even for someone who is used to following the rules.
- 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 comma is the syntax of the tuple constructor.
- A tuple is created on the right (tuple package).
- The tuple on the left is the target of the assignment (unpacking the tuple).
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