Zalecenia programistyczne:
- Kod powinien być pisany w sposób, który nie powoduje problemów w innych implementacjach Pythona (PyPy, Jython, IronPython, Pyrex, Psyco i innych)
Dla przykładu nie należy polegać na implementacji łączenia ciągów “w miejscu” (in-place) w formie a+=b lub a=a+b. Takie deklaracje wykonują się dużo wolniej w Jython. W częściach biblioteki gdzie wydajność jest szczególnie ważna w zamian powinna być użyta konstrukcja ”.join(). Taka konstrukcja daje pewność, że połączenie zdarzy się liniowo w czasie pośród różnych implementacji.
- Porównania do singletonów takich jak None zawsze powinno być robione przy pomocy is lub is not, nigdy operatorów porównania.
Wystrzegać należy się pisania if x kiedy ma się na myśli if x is not None — np. kiedy testuje się czy danej zmiennej czy argumentowi, który domyślnie przyjmuje wartość None została przypisana inna wartość. Inne wartości mogą mieć taki typ (tak jak kontener), że jest on fałszywy w kontekście booleanowskim (?).
- Używać klas wyjątków w Pythonie (class-based exceptions)
Wyjątki typu string w nowym kodzie są zabronione, ponieważ ta właściwość języka zostanie usunięta w Pythonie 2.6.
Moduły i pakiety (packages) powinny definiować własne specyficzne dla siebie klasy wyjątków (exception class), które powinny dziedziczyć z wbudowanej (built-in) klasy wyjątków. Zawsze należy zawierać docstringa klasy.
Mają tutaj również zastosowanie konwencje nazewnictwa klas, chociaż powinno dodawać się sufiks Error do nazwy klasy wyjątku, jeśli wyjątek jest błędem. Wyjątki “nie-błędy” nie potrzebuję specjalnego sufiksu.
class MessageError(Exception): """Base class for errors in the email package."""
- Kiedy podnosi się wyjątek należy używać raise ValueError(’message’) zamiast starszej formy raise ValueError, ‘message’.
Forma z nawiasami jest preferowana, ponieważ kiedy argumenty wyjątku są długie lub zawierają formatowanie ciągów nie zachodzi potrzeba używania znaku kontynuacji linii dzięki otoczeniu nawiasami. Starsza forma będzie niedostępna w Pythonie 3000.
- Podczas przechwytywania wyjątków, należy podać jaki wyjątek się przechwytuje kiedykolwiek to jest możliwe, zamiast używać “czystej” klauzuli except.
Na przykład:
try: import platform_specific_module except ImportError: platform_specific_module = None
Samotna klauzula except przechwyci także wyjątki SystemExit i KeyboardInterrupt, co uczyni trudniejszym przerwanie działania programu przy pomocy
i przesłoni inne, nieprzewidziane problemy. W przypadku potrzeby łapania wszystkich wyjątków, które sygnalizują błędy w programie należy używać except Exception Dobrą zasadą jest ograniczyć użycie czystego except do dwóch przypadków:
- Jeśli uchwyt (?) wyjątku będzie drukował log ze śledzenia błędu (traceback), przynajmniej użytkownik będzie świadom, że wystąpił błąd.
- Jeśli kod wymaga wyczyszczenia, lecz wtedy pozwala wyjątkowi propagować się w górę z raise (?). W takim wypadku try…finally jest lepszym sposobem aby obsłużyć wyjątek.
- Dodatkowo, dla wszystkich klauzuli try/except należy ograniczać ilość kodu pod klauzulą try do niezbędnego minimum. Również to pomoże unikać błędów.
Tak:
try: value = collection[key] except KeyError: return key_not_found(key) else: return handle_value(value)
Nie:
try: # Too broad! return handle_value(collection[key]) except KeyError: # Will also catch KeyError raised by handle_value() return key_not_found(key)
- Używać metod stringów, a nie modułu string
Metody stringów są zawsze dużo szybsze i współdzielą to samo API ze stringami unikod.
- Należy używać ”.startswith() i ”.endswith() zamiast krojenia stringów (string slicing).
startswith() i endswith() są czystsze i powodują mniej błędów. Na przykład:
Tak:
if foo.startswith('bar'):
Nie:
if foo[:3] == 'bar':
- Porównania typów obiektowych powinny zawsze używać konstrukcji isinstance() zamiast porównywać typy bezpośrednio.
Tak:
if isinstance(obj, int):
Nie:
if type(obj) is type(1):
Podczas sprawdzania czy obiekt jest stringiem, należy mieć na uwadze, że to również może być string unikodowy! W Pythonie 2.3 string i unikod mają wspólną klasę bazową, basestring, tak więc można zrobić:
if isinstance(obj, basestring):
- Dla typów sekwencyjnych, (stringów, list, krotek/tuples/), należy korzystać z faktu, że puste sekwencje są fałszywe.
Tak:
if not seq: if seq:
Nie:
if len(seq) if not len(seq)
- Nie należy pisać stringów, które zawierają znaczący niedrukowalny znak (spacja, tabulator), Niektóre takie znaki nie dają się od siebie odróżnić i niektóre edytory (lub ostatnio, reindent.py) obetną je.
- Nie wolno porównywać booleanowskich wartości do True lub False używając ==.
Tak:
if greeting:Nie:
if greeting == True:
Jeszcze gorzej:
if greeting is True:
Napisane na podstawie PEP 8 . Nie jestem profesjonalistą, ale staram się. Tekst jest pomocą przede wszystkim dla mnie. Jeśli komuś jeszcze będzie on pomocny ucieszę się. Jeszcze bardziej będę zadowolony jeśli ktoś doświadczony tu zajrzy i zechce skomentować to, i tamto.
