Buch Beyound the basic stuff with Python
3. Code formatting
- guideline PEP8
- usage of tabulators/indentation
- one line per import command
- usage of Black formatter
4. naming variables and others
- only ASCII letters
- modules: all lowercase
- classes: PascalCase
- constants: uppercase SNAKE_CASE
- functions, methods & variables: lowercase snake_case
- private attributes: start with '_'
- use telling names
names
<Verb>[<Adjektiv>]<Substantiv>[<Struktur>]
e.g. get_unanswered_questions_list
- Suchen und Beschaffen
- get => compute, acquire, fetch, download, tetrieverequest (async), query
- find/search => =! seek, search sth = in etw. suchen
- include
- scan => find, search
- Anzeigen
- dump => (debugging)
- render
- show/hide (as counterparts) => display
- Verbinden
- join/merge
- append/concatenate => combine
- combine => splice, concatenate
- Zerlegen
- split => counterpart: join
- slice, splice
- Umwandeln
- parse => render, serialize
- to_something => convert_to_something
- invert/reverse
- Anfangen/Aufhören
- start-stop/begin-end/open-close
- pause/stop/exit
- destruct/destroy/kill
- Auf- und Umräumen
- flush
- clear/purge
- cleanup
- collapse/compact => collapse-expand
- move => =! copy
- tidy/pretty/beautify
- dauerhaft machen
- save/store/write
- commit => (SQL)
- bake
- Umkehren
- undo-redo
- rollback => (database)
- restore/revert (version control)
- recover
- mit Vorsicht
- process/do/perform/deal_with/manage/change/handle/resolve
- filter => select, find extract, reject, exclude, strip
- check/validate/verify/test => is_valid, is_open
- Boolesch
- is_done, has_error, is_valid => Verneinungen vermeiden
- falsche Freunde
- actual != aktuell (= tatsächlich) => current
- make => (Compiler)
- number (known amount) =>digit, count (counter)
- form == Formular => shape
- control (continously) => check, verify
- eventually != eventuell (= schließlich)
- limit/border => lower_limit, upper_limit, threshold
- faculty =! math. Fakultät => factorial
- concurrent =! Konkurrenz (= nebenläufig)
- address, resource, authentication => adress, ressource, authentification
5. code smells
- duplicate code => define function, repeated call
- magic number => make clear the context
- no commented-out code or dead code (in final version)
- debugging using logging instead of print
import logging
logging.basicConfig(filename='log_filename.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('This is a log message.')
- variables with (consecutive) numeric suffixes => use list instead
- use list compehension but no nested list comprehension
6. pythonic code
- Zen of Python => rules for better code
- use enumerate() instead of range(len(object))
- use with instead of open() and close()
- 'var is None' instead of 'var == None'
- use f-strings and r-strings
- dicts: get() offer default valus, setdefault() assigns only if not existant
mydict.get("key", default_value) # just read value
mydict.setdefault("key", default_value) # in case to be used further
import collections
mydict = collection.defaultdict(int) # every entry has default value
mydict = {"mo": "monday", "tue": "tuesday", "wed": "wednesday"}
day = mydict.get(short_day, "not known")
- use collections.defaultdict to set general default value(s)
- dict() can replace switch statement (repeated if-then)
- conditional expressions can be used
7. jargon
- python language & interpreter
- garbage collection
- literals
- keywords
- objects, values, instances, identities
- items
- mutable & immutable
- indexes, keys, hashes
- containers, sequences, mapping, set types
- dunder methods, magic methods
- modules & packages
- callables, first-class objects
- statements vs. expressions
- block vs. clause vs. body
- variable vs attribute
- function vs. method
- iterable vs. iterator
- syntax vs. runtime vs. sematic errors
- parameters vs. arguments
- bytecode vs. machine code
8. gotchas
- don't add/remove items to/from a list while iterating
- always copy mutables with copy.deepcopy()
- copy.copy() creates a new object
- copy.deepcopy() creates also new objects for nested mutables (list in list)
- don't use mutables for default arguments
- default argument is only created once when def-statement is executed
- instead, use None and create new object within the function
- avoid multiple concatenation of strings
- instead, use a list and final .join() function
9. esoteric oddities
- pre-defined int objects for numbers from -5 to 256
- all() => not "all are true" but rather "none is false"
- bool is sub-class of int
- True = 1
- False = 0
10. effective functions
- short: easy, more simple, less parameters but more complex structure, more names
- trade-off: function with 30-200 lines
- default argument if value is mostly used
- when calling functions
- '*' => flatten list to several single entries
- '**' => convert dict to '\
= \ ' entries
- within def of function
- '*args' => list of all positional arguments
- '**args' => dict of all key/value arguments
def myfunction(**kwargs):
if kwargs.get(key) == value:
...
- map(function, list) => apply function to every item of list (can also be lambda function)
- filter(function, list) => filter object returning items that pass the function
- list comprehension meist besser als map oder filter
- always return the same data type (within one function)
- using exceptions prevents functions from failing silent