10.1. Good Practices

10.1.1. Rationale

../../_images/goodpractices-programmer-exp.png

Figure 10.1. Code Complexity vs. Programmer Experience

10.1.2. Range

>>> i = 0
>>>
>>> while i < 5:
...    i += 1
>>> for i in range(5):
...    pass

10.1.3. ForEach

For:

for (int i = 0; i <= 10; i++)  # C/C++/Java
for (var i = 0; i <= 10; i++)  # JavaScript

i = 0
while i <= 10:  #  Python
    i += 1

ForEach Element:

for (var element : collection)   # Java
for (let element of collection)  # JavaScript
for element in collection        # Python
for i in range(0,10)             # Python

ForEach Index:

for (let idx in collection)         # JavaScript
for idx in range(len(collection))   # Python
>>> DATA = ['a', 'b', 'c']
>>>
>>> for i in range(len(DATA)):
...    value = DATA[i]
>>> DATA = ['a', 'b', 'c']
>>> for value in DATA:
...    pass

10.1.4. Sum

>>> DATA = [1, 2, 3]
>>> total = 0
>>>
>>> for i in range(len(DATA)):
...    total += DATA[i]
>>> DATA = [1, 2, 3]
>>> sum(DATA)
6

10.1.5. Enumerate

>>> DATA = ['a', 'b', 'c']
>>> i = 0
>>>
>>> while i < len(DATA):
...    value = DATA[i]
...    i += 1
>>> DATA = ['a', 'b', 'c']
>>>
>>> for i, value in enumerate(DATA):
...    pass

10.1.6. Zip

>>> header = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> result = {}
>>>
>>> for i in range(len(header)):
...    key = header[i]
...    val = values[i]
...    result[key] = value
>>> header = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>>
>>> result = zip(header, values)
>>> dict(result)
{'a': 1, 'b': 2, 'c': 3}

10.1.7. List Comprehension

>>> DATA = ['a', 'b', 'c']
>>> result = list()
>>>
>>> for x in DATA:
...    result.append(x)
...
>>> result
['a', 'b', 'c']
>>> DATA = ['a', 'b', 'c']
>>> result = [x for x in DATA]
>>> result
['a', 'b', 'c']

10.1.8. Set Comprehension

>>> DATA = ['a', 'b', 'c']
>>> result = set()
>>>
>>> for x in DATA:
...    result.add(x)
>>> DATA = ['a', 'b', 'c']
>>> result = {x for x in DATA}

10.1.9. Dict Comprehension

>>> DATA = {'a': 1, 'b': 2, 'c': 3}
>>> result = dict()
>>>
>>> for key, value in DATA.items():
...    result[key] = value
>>> DATA = {'a': 1, 'b': 2, 'c': 3}
>>> result = {k:v for k,v in DATA.items()}

10.1.10. Map

>>> def func(x):
...     return float()
...
>>> DATA = [1, 2, 3]
>>> result = (func(x) for x in DATA)
>>> def func(x):
...     return float()
...
>>> DATA = [1, 2, 3]
>>> result = map(func, DATA)

10.1.11. Filter

>>> def func(x):
...     return x % 2 == 0
...
>>> DATA = [1, 2, 3]
>>> result = (x for x in DATA if func(x))
>>> def func(x):
...     return x % 2 == 0
...
>>> DATA = [1, 2, 3]
>>> result = filter(func, DATA)

10.1.12. For Else

>>> DATA = [1, 2, 3]
>>> FIND = 10
>>> found = False
>>>
>>> for value in DATA:
...     if value == FIND:
...         print('Found')
...         found = True
...         break
...
>>> if not found:
...     print('Not Found')
Not Found
>>> DATA = [1, 2, 3]
>>> FIND = 10
>>>
>>> for value in DATA:
...     if value == FIND:
...         print('Found')
...         break
... else:
...     print('Not Found')
Not Found

10.1.13. While Else

>>> DATA = [1, 2, 3]
>>> FIND = 10
>>> found = False
>>>
>>> while i < len(DATA):
...     value = DATA[i]
...     i += 1
...     if value == FIND:
...         print('Found')
...         found = True
...         break
...
>>> if not found:
...     print('Not Found')
Not Found
>>> DATA = [1, 2, 3]
>>> FIND = 10
>>>
>>> while i < len(DATA):
...     value = DATA[i]
...     i += 1
...     if value == FIND:
...         print('Found')
...         break
... else:
...     print('Not Found')
Not Found

10.1.14. Str Startswith

>>> data = 'virginica'
>>> data[:1] == 'v'
True
>>> data[:1] == 'v' or data[:1] == 's'
True
>>> data = 'virginica'
>>> data.startswith('v')
True
>>> data.startswith(('v', 's'))
True

10.1.15. Str Endswith

>>> data = 'virginica'
>>> data[-3:] == 'osa'
False
>>> data[-3:] == 'osa' or data[-2:] == 'ca'
True
>>> data = 'setosa'
>>> data.endswith('osa')
True
>>> data.endswith(('osa', 'ca'))
True

10.1.16. Str Join Newline

>>> data = ['line1', 'line2', 'line3']
>>> result = [line+'\n' for line in data]
>>> data = ['line1', 'line2', 'line3']
>>> result = '\n'.join(data)

10.1.17. Others

  • all()

  • any()

  • iter()

  • next()

10.1.18. Functools

>>> from functools import *

10.1.19. Itertools

  • https://docs.python.org/3/library/itertools.html

  • More information in Itertools

  • count(start=0, step=1)

  • cycle(iterable)

  • repeat(object[, times])

  • accumulate(iterable[, func, *, initial=None])

  • chain(*iterables)

  • compress(data, selectors)

  • islice(iterable, start, stop[, step])

  • starmap(function, iterable)

  • product(*iterables, repeat=1)

  • permutations(iterable, r=None)

  • combinations(iterable, r)

  • combinations_with_replacement(iterable, r)

  • groupby(iterable, key=None)

>>> from itertools import *

10.1.20. The Zen of Python

>>> import this
The Zen of Python, by Tim Peters
<BLANKLINE>
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Polish:

  • Piękne jest lepsze niż brzydkie.

  • Wyrażone wprost jest lepsze niż domniemane.

  • Proste jest lepsze niż złożone.

  • Złożone jest lepsze niż skomplikowane.

  • Płaskie jest lepsze niż wielopoziomowe.

  • Rzadkie jest lepsze niż gęste.

  • Czytelność się liczy.

  • Sytuacje wyjątkowe nie są na tyle wyjątkowe, aby łamać reguły.

  • Choć praktyczność przeważa nad konsekwencją.

  • Błędy zawsze powinny być sygnalizowane.

  • Chyba że zostaną celowo ukryte.

  • W razie niejasności powstrzymaj pokusę zgadywania.

  • Powinien być jeden -- i najlepiej tylko jeden -- oczywisty sposób na zrobienie danej rzeczy.

  • Choć ten sposób może nie być oczywisty jeśli nie jest się Holendrem.

  • Teraz jest lepsze niż nigdy.

  • Chociaż nigdy jest często lepsze niż natychmiast.

  • Jeśli rozwiązanie jest trudno wyjaśnić, to jest ono złym pomysłem.

  • Jeśli rozwiązanie jest łatwo wyjaśnić, to może ono być dobrym pomysłem.

  • Przestrzenie nazw to jeden z niesamowicie genialnych pomysłów -- miejmy ich więcej!