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,158