Standarde de scriere în Python
Alexandru Coman
www.alexcoman.com
alex@ropython.org
Cuprins
I. Motivație
II. PEP 8
motivație, sugestii, exemple
III. Google Style
diferențe față de PEP 8
IV. Recomandări
pylint, pep8, flake8
V. Concluzie
I. Motivație
În momentul în care scrii un fragment de cod gândește-te că persoana care urmează să-l întrețină știe unde locuiești!
[1]
II. PEP 8
O suită de sugestii menite să ușureze citirea și înțelegerea codului.
Este destinat bibliotecilor standard de Python dar este adoptat și de alți dezvoltatori.
I. Aspectul codului sursă
{"indentare": (4, "spații"), "lugime_linie": 79}
II. Spațiile din cadrul expresiilor
III. Convențiile de nume
{"clasa": "ClasaMea", "functie": "functia_mea"}
IV. Sfaturi pentru dezvoltatori
II. PEP 8 - Aspectul codului
I. Indentarea
- se folosesc 4 spații.
- nu se recomandă mixarea spațiilor cu tab-uri.
II. Tab-uri sau spații
- se recomandă folosirea spațiilor pentru identare
III. Lungimea liniei
- lungimea recomandată pentru o linie este de 79 de caractere
- în cazul unei linii mai mari de 79 se recomandă împărțirea ei pe mai multe linii
- lungimea unei linii dintr-un docstring se recomandă a fi 72 de caractere
II. PEP 8 - Aspectul codului
IV. Importurile
- importurile trebuie să fie pe o singură linie
- se recomandă importarea modulelor în ordinea importanției
- biblioteci standard
- biblioteci din alte surse
- biblioteci locale
# Biblioteci standard
import os
import sys
from subprocess import Popen, PIPE
# Biblioteci externe
from jarvis.worker import Daemon
# Biblioteci locale
import proiect.procesator as procesator
from .procesator import procesator as procesator2
II. PEP 8 - Aspectul codului
# Putem sa folosim identarea pentru a evidenția conținutul
matrice = [
1, 2, 3, 4,
5, 6, 7, 8]
alta_matrice = [1, 2, 3, 4,
5, 6, 7, 8]
# Adăugăm încă un nivel de indentare pentru a nu se confunda cu corpul
# funcției.
def long_function_name(
variabila_unu, variabila_doi, variabila_trei,
variabila_patru):
print(variabila_unu)
# Adaugăm indentare pentru a continua pe linie nouă
foo = long_function_name(
var_one, variabila_doi,
variabila_trei, variabila_patru)
# Aliniem argumentele de pe al doilea rând sub primul argument
functie_cu_multe_argumente("RoPython", eveniment="Workshop #1", locatie="UAIC",
durata=7200, participanti=50)
II. PEP 8 - Spațiile din expresii
"""Nu se pun spații după paranteze sau acolade"""
# Greșit
oferă("premii", { "bilete_ropython": 5, "tricouri": 0 } )
# Corect
oferă("premii", {"bilete_ropython": 5, "tricouri": 0})
"""Nu se pun spații înainte de virgulă"""
# Greșit
if raspuns == "ropython": print participant , premiu
# Corect
if raspuns == "ropython": print participant, premiu
"""Nu se pune spațiu după numele unui obiect"""
# Greșit
ropython ['participanți'] = informatii [index]
# Corect
ropython['participanți'] = informatii[index]
"""Nu se adaugă spații inutile pentru alinierea valorilor"""
# Greșit
var_a = 10
var_b = 11
acceleratie = 20
# Corect
var_a = 10
var_b = 11
acceleratie = 20
II. PEP 8 - Convenții de nume
-
numele funcțiilor se scriu cu litere mici și cuvintele sunt separate de _
-
fiecare cuvant din numele unei clase se scrie cu literă mare
-
elementele interne se marchează cu _nume
-
pentru a evita conflictul cu un keyword se folosește nume_
-
__nume se folosește pentru atributele unei clase
-
__magic__ - obiecte magice
- sunt nume rezervate de limbajul Python
- nu vă creați unul propriu
II. PEP 8 - Convenții de nume
"""
folosim _ pentru a marca elementele ce interne
"""
# Nume de clasa
class NumeClasa(object):
__atribut = 10
# __lower_case__ - obiect "magic"
def __init__(self):
pass
# Clasa pentru uz intern în modul
class _NumeClasa(object):
pass
II. PEP 8 - Sfaturi
"""Se recomandă evitarea formularilor vechi"""
# Varianta recomandată
try:
# Ceva cod interesant aici
except ValueError as exc:
raise ValueError("Operație imposibilă !")
# Varianta greșită
try:
# Ceva cod interesant aici
except ValueError, exc:
raise ValueError "Operație imposibilă !"
# Dezastruos
try:
# Ceva cod interesant aici
except:
pass
PEP 8 - Sfaturi
"""Greșeli comune"""
# Recomandat
if foo.startswith('bar'): pass
# Nerecomandat - Poate cauza probleme
if foo[:3] == 'bar': pass
# Practica cea mai eleganta
if isinstance(obj, int): pass
# Nerecomandat
if type(obj) is type(1): pass
# Ok
if ceva is None: pass
if not ceva: pass
if ceva: pass
# Greșit
if ceva == True: pass
# Foarte greșit
if ceva is True: pass # Și ceva poate fi doar `True` sau `False`
if ceva == None: pass
III. Google Style
Standardul recomandat de Google aduce câteva modificări standardului PEP8
- limita de caractere pe rând devine 80
- se recomandă folosirea operatorului % pentru formatarea stringurilor
- se recomandă evitarea folosirii operatorilor + și += pentru concatenarea stringurilor
- se recomandă folosirea comentariului TODO
III. Google Style - Convenții de nume
Type | Public | Internal |
---|---|---|
Packages | lower_with_under | |
Modules | lower_with_under | _lower_with_under |
Classes | CapWords | _CapWords |
Exceptions | CapWords | |
Functions | lower_with_under() | _lower_with_under() |
Global/Class Constants | CAPS_WITH_UNDER | _CAPS_WITH_UNDER |
III. Google Style - Convenții de nume
Type | Public | Internal |
---|---|---|
Global/Class Variables | lower_with_under | _lower_with_under |
Instance Variables | lower_with_under | _lower_with_under __lower_with_under |
Method Names | lower_with_under() | _lower_with_under() __lower_with_under() |
Function/Method Parameters | lower_with_under | |
Local/Variables | lower_with_under |
Recomandări
PyLint - http://www.pylint.org/
W: 5, 0: Bad indentation. Found 3 spaces, expected 4 (bad-indentation)
W: 8, 0: Bad indentation. Found 3 spaces, expected 4 (bad-indentation)
W: 9, 0: Bad indentation. Found 3 spaces, expected 4 (bad-indentation)
W: 10, 0: Bad indentation. Found 3 spaces, expected 4 (bad-indentation)
W: 11, 0: Bad indentation. Found 7 spaces, expected 8 (bad-indentation)
W: 12, 0: Bad indentation. Found 3 spaces, expected 4 (bad-indentation)
C: 13, 0: Trailing whitespace (trailing-whitespace)
W: 31, 0: Bad indentation. Found 7 spaces, expected 8 (bad-indentation)
W: 7, 0: Redefining built-in 'dir' (redefined-builtin)
C: 1, 0: Missing module docstring (missing-docstring)
C: 4, 0: Missing class docstring (missing-docstring)
W: 4, 0: Class has no __init__ method (no-init)
R: 4, 0: Too few public methods (0/2) (too-few-public-methods)
C: 7, 0: Missing function docstring (missing-docstring)
W: 15, 3: Unreachable code (unreachable)
W: 12,10: Using possibly undefined loop variable 'file' (undefined-loop-variable)
W: 7,14: Unused argument 'dirs' (unused-argument)
C: 17, 0: Missing function docstring (missing-docstring)
E: 20,10: Catching an exception which doesn't inherit from BaseException: SomeError (catching-non-exception)
C: 26, 0: Missing class docstring (missing-docstring)
Recomandări
Flake8 - http://flake8.readthedocs.org/
$ flake8 coolproject
coolproject/mod.py:97:1: F401 'shutil' imported but unused
coolproject/mod.py:625:17: E225 missing whitespace around operato
coolproject/mod.py:729:1: F811 redefinition of function 'readlines' from line 723
coolproject/mod.py:1028:1: F841 local variable 'errors' is assigned to but never used
$ flake8 --max-complexity 12 coolproject
coolproject/mod.py:97:1: F401 'shutil' imported but unused
coolproject/mod.py:625:17: E225 missing whitespace around operator
coolproject/mod.py:729:1: F811 redefinition of unused 'readlines' from line 723
coolproject/mod.py:939:1: C901 'Checker.check_all' is too complex (12)
coolproject/mod.py:1028:1: F841 local variable 'errors' is assigned to but never used
coolproject/mod.py:1204:1: C901 'selftest' is too complex (14)
Link-uri utile
-
PEP 8 Style Guide for Python Code - http://legacy.python.org/dev/peps/pep-0008/
-
Google Python Style Guide - https://google-styleguide.googlecode.com/svn/trunk/pyguide.html#Global_variables
-
PyLint - http://www.pylint.org/
-
Pep8 checker - https://github.com/jcrocholl/pep8
Concluzie
Câteodată standardul de scriere nu poate fi aplicat.
Atunci când ai dubii nu improviza!
Întrebări ?
Referințe
[1] The Joker Pencil Drawing by JLeonardK
[2] Introducere în Pylint - http://blog.ropython.org/pylint/
Standarde de scriere în Python
By Alexandru Coman
Standarde de scriere în Python
Prezentarea atrage atenția asupra importanței folosirii unui standard de scriere a codului în Python în detrimentul implementării conform propriului standard.
- 2,202