What is Pythonico?
The expression pythonic, originated in English, pythonic, is a vague expression, that is, without an exact meaning. It is usually used to reference a code idiomatic in Python. The term became famous and used worldwide mainly for the success that Python makes with some extremely simple solutions. I’ve heard quotes saying, "if you didn’t do it in a line of code, you did it wrong". Of course this is not literal, but it expresses as well as the language approach.
What makes a code count pythonic?
Created with Tim Peters, a BDFL of the Python language, and extremely well received by the community, the group of 20 aphorisms known as The Zen of Python (PEP 20) is the main point for defining whether a code is idomatic or not. Defined by Guido van Rossum himself, creator of language, as the perfect description of Python’s philosophy, it is enough to make a code consistent with all aphorisms to have an idiomatic code. It’s them:
(1) Beautiful is Better than Ugly.
Beautiful is better than ugly.
(2) Explicit is Better than implicit.
Explicit is better than implicit.
(3) Simple is Better than Complex.
Simple is better than complex.
(4) Complex is Better than Complicated.
Complex is better than complicated.
(5) Flat is Better than nested.
Flat is better than nestled.
(6) Sparse is Better than Dense.
Sparse is better than dense.
(7) Readability Counts.
Readability counts.
(8) Special cases aren’t special enough to break the Rules.
Special cases aren’t special enough to break the rules.
(9) Although practicality Beats purity.
Though practicality overcome purity.
(10) Errors should Never pass Silently.
Mistakes must never pass silently.
(11) Unless explicitly silenced.
Unless they are explicitly silenced - see aphorism 2.
(12) In the face of ambiguity, refuse the temptation to Guess.
In the face of ambiguity, refuse the temptation to guess.
(13) There should be one-- and preferably only one --obvious way to do it.
There should be one - and preferably only one - obvious way to do something: the way pythonic.
(14) Although that way may not be obvious at first unless you’re Dutch.
Although this way may not be obvious at first unless you are Dutch.
(15) Now is Better than Never.
Now it’s better than ever.
(16) Although Never is often Better than right now.
Though it’s never often better than now.
(17) If the implementation is hard to explain, it’s a bad idea.
If implementation is difficult to explain, it’s a bad idea.
(18) If the implementation is easy to explain, it may be a good idea.
If the implementation is easy to explain, it might be a good idea - but not necessarily.
(19) Namespaces are one honking Great idea -- Let’s do more of those!
Namespaces are a great idea - let’s have more of these!
If you notice, aphorism 7 indicates that code readability is important. Indeed, it is, so much so that one of the main items taken into account by Guido van Rossum in creating the language was that the code should be readable to humans just as easily as a machine could read it. That is, structures should follow an organization that gets as close to the developer’s everyday writing as possible, using indentation blocks to manage contexts. Code formatting is so important in Python that the main Python Enhancement Proposals (PEP) is the one that defines the style guide for Python codes: PEP 8. And no one more suited than the creator of language himself to define what’s best for her, right? The document is relatively long and unviable to transcribe it here, but this should not reduce its importance. For ease, you can install in your editor some component related to Python Lint that he will probably guide you as per all PEP 8 recommendations.
Examples
Below is a list of simple examples that are considered and accepted by the community as pythonicos.
Exchanging values in variables
Other languages:
int x = 1,
y = 2,
temp;
temp = x;
x = y;
y = temp;
Python:
x = 1
y = 2
x, y = y, x
The code works because what actually happens is a tuple treatment. The right-hand syntax, y, x
, generates a tuple of two values (tuple Packing). The syntax on the left side does the opposite (tuple unpacking), assigning each tuple position to a variable, causing x
receive the value of y
and y
the value of x
.
Statement of switch
?
Other languages:
int num = 3;
switch (num) {
case 0:
...
case 1:
...
case 2:
...
default:
...
}
There is no building switch
in Python. Pythonic way of doing is by using a dictionary.
opcoes = {
1: uma_funcao_qualquer,
2: outra_funcao_qualquer,
3: mais_uma_funcao
}
And call function that:
opcoes[variavel_inteira]()
In this way, opcoes[variavel_inteira]
will return the respective function and will be executed immediately due to the ()
at the end of the line.
Statement of do .. while
?
For the validation of a user input value, for example, it is common that we have to ask for a new value until it is valid. In other languages there is the structure do..while
, but not in Python. See the example for reading a natural value:
Other languages:
int num;
do {
scanf("%d", &num);
} while (num < 0);
Python:
while True:
num = int(input())
if num >= 0:
break;
In other words, in Python an infinite loop is created with while True
and internally is checked whether the desired condition has been satisfied, ending the loop with break
.
Browsing a list with key/value:
It is quite common that we have to go through a list of values using both the key and the value of this list. Some languages provide the structure foreach
which returns the key/value pair, but in Python, the structure for
returns only the value.
Other languages:
int seq[5] = {0, 1, 2, 3, 4};
for (int i = 0; i < 5; i++) {
printf("%d, %d\n", i, seq[i]);
}
Python:
seq = [0, 1, 2, 3, 4]
for key, value in enumerate(seq):
print(key, value)
Access to the key/value pair is done through the function enumerate
, that returns a tuple of two values: the first the key and the second the value. Within the for
is made a tuple unpacking for the variables key
and value
.
Testing Empty/Void:
In Python, any and all variables tested as boolean returns False
in the following cases:
False
None
0
, whatever the numerical type
- Empty sequences (
''
, ()
, []
)
- Empty mapping:
{}
- Instances of "empty" classes, whose classes implement or
__nonzero__()
(and return False
) or __len__()
(and return zero).
This is useful for testing sequences with empty, false or zeroed values:
for item in lista:
if item: print(item)
Traverse lines from a file
Python:
with open("/tmp/arquivo.txt") as file:
for line in file:
print(line) # line possui o conteúdo de cada linha
For more details on with
, read What’s with no Python for?. The native function open
returns a Generator that will iterate over the file, this way it is possible to use the object directly in a repeat loop, without having to store the entire contents of the file in memory.
Mandatory references and readings
[1] The Zen of Python: https://www.python.org/dev/peps/pep-0020/
[2] Style Guide for Python Code: https://www.python.org/dev/peps/pep-0008/
Related: http://answall.com/q/184238/41056
– vinibrsl