Menu Zamknij
30 września 2021

Python 3.10 - Co nowego?

Wstęp

Python jest językiem nieustannie rozwijanym i co rusz wypuszczane są jego kolejne standardy, a wraz z nimi nowe ciekawe feature-y. Dlatego podążając za zmieniającym się rynkiem pracy i jego technologiami, przygotowaliśmy artykuł, który opisuje najważniejsze zmiany w najnowszej wersji wspomnianego języku - Pythona 3.10. Pełny release jest przewidziany na najbliższy okres czasu - początek października roku 2021. Dlatego też warto już teraz zapoznać się ze wszystkimi nowościami, abyśmy choćby my - mentorzy programowania, mogli z naszymi uczniami tworzyć projekty zgodne z najnowszymi wytycznymi.

Feature I
Dokładniejsze raportowanie błędów

Jeżeli jesteś już nieco bardziej wprawionym programistą Pythona, to zapewne wiesz, że szukanie w kodzie, tzw. Syntax Errorów, może być dość mozolną pracą. Oczywiście, nie powinniśmy na to aż tak bardzo narzekać, szczególnie biorąc pod uwagę, iż Python ma relatywnie prostą składnię w stosunku do innych wysokopoziomowych języków programowania, jak, np. Java czy C++. Mimo to komitet standaryzacyjny Pythona, postanowił zatwierdzić pomysł wprowadzenia nowych - bardziej czytelnych - błędów parsowania kodu. 

Tak więc od teraz, błędy pokroju:

         - SyntaxError: invalid syntax

zostaną zastąpione bardziej dokładnymi, wyraźnie wskazującymi, gdzie leży błąd:

         - SyntaxError: '(' was never closed

Spójrz na przykłady poniżej i postać błędów, jaka od teraz będzie wyświetlana:

students_age = {'George': 30, 'Adam': 20, 'Jan': 25, 'Kacper': 33, 'Ann': 39
calc_sth()

Wcześniejsza wersja interpretera Pythona poinformowałaby o następującym błędzie:

File "<string>", line 3
    calc_sth()
SyntaxError: invalid syntax

natomiast w Python 3.10, otrzymamy:

File "<string>", line 1
    students_age = {'George': 30, 'Adam': 20, 'Jan': 25, 'Kacper': 33, 'Ann': 39
SyntaxError: '{' was never closed

Zauważ więc, że od tego momentu mamy informację na temat konkretnego miejsca, w którym nastąpił błąd oraz dokładnie sprecyzowanie, o czym zapomnieliśmy. 

Poniżej dodatkowo kilka innych błędów, które zostały “podrasowane” w zbliżającej się wersji języka:

      1. Brak dwukropka przed ciałem struktury (np. if-a).

File "<string>", line 1
    if number % 2 == 0
SyntaxError: expected :

      2. Brakujące przecinki przy inicjalizowaniu złożonej struktury danych, np. słownika.

Syntax Error z Pythona 3.9:

File "<string>", line 6
   'Ann': 39
SyntaxError: invalid syntax

     3. Comma Error z Pythona 3.10:

items = {
  File "<string>", line 3
    ‘Ann’: 39
SyntaxError: invalid syntax. Perhaps you forgot a comma?

     4. Wprowadzono również obsługę Syntax Erroru dla chyba jednego z najczęściej popularnego błędu przez początkujących - użycie operatora = zamiast == przy instrukcjach warunkowych

File "<string>", line 1
    if name = 'Devs':
SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='?

Feature II
Structural Pattern Matching

Jest to najprawdopodobniej jedna z największych i najciekawszych zmian w najnowszej wersji Pythona.  Jest to pewnego rodzaju alternatywa dla obecnie szeroko wykorzystywanego wyrażenia if. Jeżeli znasz takie języki jak, np. Java czy JavaScript, to zapewne kojarzysz strukturę switch… case. Structural Matching Pattern wprowadzany teraz w nowym standardzie jest właśnie odpowiednikiem wspomnianego switcha. Z tą różnicą, że w Pythonie ta struktura będzie występowała w postaci match… case

Dla mniej wtajemniczonych - match… case uznaje się za ładniejszą wersją ifa, gdy potrzebujesz stworzyć wiele porównań do konkretnej wartości. Oczywiście możesz to zrealizować, tak jak do tej pory - czyli przy użyciu ifologii - ale co do zasady, od wersji 3.10 ładniej będzie użyć nowego rozwiązania. 

Spójrz na przykłady poniżej:

key = input("Type a secret key: ")

 

if key == 'Devs-Mentoring':

    print("Passed")

elif key == 'Devs Mentoring':

    print("Close enough!")

elif key == 'Devs':

    print("Too short!")

elif key == '':

    print("You should type in something!")

else:

    print("Error!")

Pojawia się w nim znaczna ilość porównań do konkretnych wartości. Znacznie efektywniej (i przede wszystkim w zgodzie z zasadami Clean Code) byłoby zapisać to w postaci:

match key:

    case "Devs-Mentoring":

        print("Passed")

    case "Devs Mentoring":

        print("Close enough!")

    case "Devs":

        print("Too short!")

    case "":

        print("You should type in anything!")

    case _:

        print("Error!")

Możemy również nieco zmienić strukturę matcha - tak, aby sprawdzał on bardziej złożone warunki:

match key:

    case "Devs-Mentoring" | "devs-mentoring":

        print("Passed")

    case "Devs Mentoring" | "devs mentoring":

        print("Close enough!")

    case "Devs" |"devs":

        print("Too short!")

    case "":

        print("You should type in anything!")

    case _:

        print("Error!")

Zwróć uwagę na zastosowanie powyżej operatora logicznego |, który ma takie samo znaczenie, co “or” w tworzonych instrukcjach warunkowych. Przykładowo warunek pierwszego case-a zostanie spełniony, gdy podamy klucz w postaci “Devs-Mentoring” lub “devs-mentoring”. 

Skoro omówiliśmy właśnie alternatywę logiczną, to warto również pochylić się na chwilę nad koniunkcją kilku warunków w strukturze match… case. Otóż, jak się zaraz przekonasz, do matcha możemy dodawać również ifa. Dzięki temu będziemy mogli łączyć dwa warunki i uzależniać jeden od drugiego.

from enum import Enum

 

class Event(Enum):

    LOGIN = 0

    LOGOUT = 1

 

ALLOWED_USERS = ['Kacper', 'Marcin', 'Adam', 'Mateusz'] 

 

def validate(event, name):

    match event:

        case Event.Login if name in ALLOWED_USERS:

            print("Logged In!")

        case Event.LOGOUT if name in ALLOWED_USERS:

            print("Logged out!")

        case _:

            print("Error!")

I tak przykładowo warunek w linii...

case Event.Login if name in ALLOWED_USERS:

... będzie spełniony, jeżeli użytkownik prześle event w postaci Event.Login oraz jego nazwa będzie się znajdowała w liście ALLOWED_USERS.

Na koniec przedstawię Ci jeszcze wskazówki, o których musisz pamiętać, posługując się matchem:

  1. Match blok nie ma swojego “scope” i definiująć w nim zmienne, będziemy je tworzyli w najbliższym zasięgu lokalnym.
  2. Nowo wprowadzone słowa match oraz case stanowią przykład: “soft keywords”. Tak więc, jeżeli w swoim dotychczasowym kodzie używałeś wspomnianych słów w postaci nazw zmiennych, to, mimo tak gruntownych zmian w Python 3.10, nie będziesz musiał tego refaktoryzować.

Feature III
Nowy Union Operator

Z racji, że Python jest językiem dynamicznie typowanym, to chcąc poprawić czytelność kodu, musimy często decydować się na wprowadzenie adnotacji typów. Dzięki temu możemy poinstruować (głównie programistów pozaprojektowych czytających nasz kod), jakie są nasze oczekiwania co do typu dla danej zmiennej. 

Przedstawienie wszystkich sposobów na typowanie różnych zmiennych to temat na oddzielne szkolenie, dlatego w tym artykule ograniczymy się jedynie do Union. Tak zaimportowana adnotacja z biblioteki typing umożliwia nam precyzowanie, że określona zmienna może być, w zależności od sytuacji, kilkoma różnymi typami, np. str, int. 

Przykładowo, chcąc stworzyć funkcję, która przyjmować będzie argument w postaci int/float, podnosić go do kwadratu i zwracać wynik, użyjemy następującej adnotacji:

from typing import Union


def square(number: Union[int, float]) -> Union[int, float]:

    return number ** 2

Od Python 3.10, to co znajduje się wyżej, możemy zapisać w następujący sposób:

def square(number: int | float) -> int | float:

    return number ** 2

O wiele wygodniejszy i krótszy sposób! 

Zakończenie

Musimy niesutannie szlifować swój zestaw umiejętności, aby być świadomymi i coraz lepszymi w fachu programistami. Rynek oraz prowadzony przez nas mentoring stawia kolejne wyzwania, a oczekiwania pracodawców od młodych programistów wciąż rosną. Tego typu artykuły mają więc pomagać w poszerzaniu swoich horyzontów i nadążaniem za nowymi trendami. A Ty jak oceniasz nowe feature-y wprowadzone w Python 3.10?

Sprawdź również nasz system mentorowania i outsourcowania specjalistów
  • Wyznaczona ścieżka od A do Z w kierunku przebranżowienia
  • Indywidualnie dostosowany materiał pod ucznia
  • Code Review ze strony mentora
  • Budowa portfolio
  • Intensywna praca z materiałami szkoleniowymi