Advent of code
Kilka dni temu rozpoczął się Advent of code. W tym roku, podobnie jak w zeszłym, wzięłam na warsztat Pythona. Odkrywam ten język właściwie na nowo - po wielu latach (i wielu nowych wydaniach) zaszło w nim wiele zmian. Oto kilka perełek, które odkryłam w trakcie rozwiązywania tegorocznych zadań:
Sortowanie topologiczne - moduł graphlib
Napisałam o sortowaniu topologicznym odrębny artykuł. Od Pythona 3.9 będzie można używać modułu graphlib.
str.format
Użycie str.format (wraz z mini-językiem) zamiast formatowania przy użyciu % (które ma dość ograniczone możliwości: %-formatownie pozwala jedynie na użycie typów int, str i double):
# str.format zamiast formatowania przy użyciu %
number = 230
data = 0X24f
print("The number is {0:+} (hex: {0:#}) \
and data is (from hex): {1:_^#10}".format(number, data))
# The number is +230 (hex: 230) and data is (from hex): ___591____Ten mini-język został wprowadzony przy formatowanych literałach napisowych(PEP-498) i daje dużo swobody w wypisywaniu wartości:
class Task:
def __init__(self, prio, desc):
self.prio = prio
self.desc = desc
tasks = [
(1, "wyrzuć śmieci"),
(10, "nastaw pranie"),
(2, "poćwicz jogę"),
(2, "poczytaj")]
for i,t in enumerate(sorted(tasks, key=lambda p: p[0])):
print("{i}) Prio {v[0]: >5}: zadanie: {v[1]}".format(v=t, i=i))
#0) Prio 1: zadanie: wyrzuć śmieci
#1) Prio 2: zadanie: poćwicz jogę
#2) Prio 2: zadanie: poczytaj
#3) Prio 10: zadanie: nastaw pranie
d = deque(map(Task, tasks))
while d:
el = d.pop()
print("popped task {t.desc} with priority {t.prio}")set.difference
Użycie set.difference (and other set-specific operations):
s1 = set("one two two three six one".split(" "))
s2 = set("one six".split(" "))
print(s1.difference(s2))
# result: {"two", "three"}Aktualizacja słownika: dict - union
Do klasy [dict] dodany został operator [union]. Istnieje kilka sposobów "łączenia" słowników, żaden z nich jednak nie wydaje się wystarczająco elegancki. W specyfikacji PEP-0584 wymmienione zostały między innymi:
Zmiana słownika w miejscu
Modyfikuje słownik d1 (tracimy oryginalne dane)
d1.update(d2)Rozpakowanie istniejących słowników
Można też utworzyć nowy słownik przy pomocy rozpakowania istniejąch słowników d1 i d2:
{**d1,**d2}To rozwiązanie nie zachowuje się dobrze dla podtypów [dict] (zawsze typem rezultatu jest [dict], niezależnie od typów składowych).
collections.ChainMap
Wrapper na dwa słowniki. Problematyczny w przypadku konfliktu kluczy: stosuje zasadę "najwcześniejsza wartość wygrywa". Dodatkowo modyfikacja zmienia słownik pod spodem.
d1 = {"A": 100}
d2 = {"B": 200}
merged = ChainMap(d1, d2)
merged["B"] = 7
d2
# {B: 7}Operator union (znak | - “pipe”)- nowość w 3.9
Dodany w Pythonie 3.9 operator union, który rozwiązuje konflikty kluczy we właściwy (to znaczy: najbardzej intuicyjny) sposób: ostatnia wartość
wygrywa.
d1 = {3: "ala", 5: "ma", 10: "kota"}
d2 = {3: "kasia", 10: "psa"}
d1 | d2
# {3: "kasia", 5: "ma", 10: "psa"}
d1
# d1 nie zmienił się
# {3: "ala", 5: "ma", 10: "kota"}
d2
# d2 nie zmienił się
# {3: "kasia", 10: "psa"}