Aktywne Wpisy
teslamodels +46
Mój największy życiowy sukces to brak gówniaków.
31 lat zaraz idę spać i bez problemów pośpie do 14.
Żadnego gówniaka nie będę musiał zawieść do szkoły.
Do tego brak kobiety i zbędnego #!$%@?.
Dużo tu osób które chcą być w związku, ale biorąc pod uwagę plusy i minusy przeważają minusy.
Dobra dosyć #!$%@? pora spać bez problemów
( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°
31 lat zaraz idę spać i bez problemów pośpie do 14.
Żadnego gówniaka nie będę musiał zawieść do szkoły.
Do tego brak kobiety i zbędnego #!$%@?.
Dużo tu osób które chcą być w związku, ale biorąc pod uwagę plusy i minusy przeważają minusy.
Dobra dosyć #!$%@? pora spać bez problemów
( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°
Runaway28 +31
#przegryw chuop na kolację zrobił sobie steka z pieczonymi ziemniakami i brokułami na parze( ͡° ͜ʖ ͡°)
Niedawno miała miejsce premiera Pythona 3.7, który przyniósł ze sobą kilka ciekawych rzeczy, jak *async*, *await*, *opóźnioną ewaluację adnotacji typów* czy *breakpoint()*. Pisałem już o tym na blogu. jak i na Steemit.
Prace nad nowymi wersjami jednak nie ustają i nadchodząca wersja - Python 3.8 prawdopodobnie również przyniesie ze sobą coś ciekawego, o czym ostatnio sporo się rozmawia.
# Co to takiego?
Otóż chodzi o możliwość przypisywania zmiennych nie tylko w stwierdzeniach a również i w wyrażeniach. Cóż to takiego znaczy?
Mała notka, nie jestem pewien, czy poprawnie przetłumaczyłem te zdania. Raczej nie korzystam z polskich źródeł i nie wiem, czy takich też używają polscy autorzy. Dla pewności chodzi mi o statement i expression.
# PEP 572
W tym dokumencie, tej propozycji wprowadzenia zmiany, którego autorami są Guido van Rossum, Chris Angelico czy Tim Peters, proponowane jest, by od wersji 3.8 Python wspierał przypisywanie zmiennych nie tylko w stwierdzeniach, ale również i wyrażeniach, za pomoca operatora
NAME := expr
.No dobrze, ale co to znaczy w praktyce. Spójrzmy na kod.
data = None
if ourfunctiongettingjson(somearg) is not None:
data = ourfunctiongettingjson(somearg)
data.dostuff()
Raczej proste do zrozumienia, zasadne, racja? Przykład z pewnego kodu wzięty. Przykład brzydki. Powyższy kod ssie w tym kontekście.
Jak można by go poprawić?
data = ourfunctiongettingjson(somearg)
if data is not None:
data.dostuff()
Możemy zrobić coś takiego, ale czy to najkrócej jak się da, najlepiej jak się da? Obecnie raczej tak, ale...
Fajnie by było, gdyby można było zadeklarować tą zmienną tam w tym ifie - zapisać po prostu wynik funkcji tam, gdzie jest ona pierwotnie używana. Ważne jest to tam, gdzie chcemy później np. wykonać jakieś operacje na wyniku wyrażenia, które wykonaliśmy, np. w warunku, ale przez to, że w wyrażeniach obecnie nie można zapisywać zmiennych, to musimy zapisać ją sobie sami, wcześniej. Czy to w pętlach, czy w list comprehensions, lambda functions czy w innych.
Obecnie inaczej się nie da. To znaczy, w tym wypadku:
if (data = ourfunctiongettingjson(somearg)) is not None:
data.dostuff()
Jedyne co otrzymamy, to błąd. Taki zapis jest nieprawidłowy.
Od Pythona 3.8 najprawdopodobniej będziemy jednak mogli zrobić coś podobnego:
if (data := ourfunctiongettinjson(somearg)) is not None:
data.dostuff()
Krócej, czyściej, lepiej.
Popatrzmy na inne przykłady.
if (match := pattern.search(data)) is not None:
match.dostuff()
Ponownie, zamiast musieć wcześniej definować zmienną, zapisać do niej dane wyrażenie, sprawdzić ją potem, możemy zrobić to w jednym miejscu.
while (value := readnextitem()) is not None:
...
Alternatywa do 2 argumentowej wersji inwokacji iter().
Teraz coś ciekawego - użycie tego w list comprehensions. Wydaje mi się, że to tutaj ten proponowany element języka będzie błyszczał.
filtereddata = [y for x in data if (y := f(x)) is not None]
Inny fajny przykład, gdzie można użyć tego operatora:
results = [(x, y, x/y) for x in inputdata if (y := f(x)) > 0]
# lub też coś takiego jak niżej
stuff = [[y := f(x), x/y] for x in range(5)]
# Gdzie to nie przejdzie?
Na razie podałem wam przykłady tego, gdzie nowego operatora
:=
można by użyć, ale gdzie będzie to zakazane?Zacznijmy od pierwszego obostrzenia -
:=
nie będzie można używać po prostu jako zamiennika=
. To by było bez sensu - dwa operatory wykonujące tą samą czynność w tych samych miejscach. Skąd wtedy wiedzieć, którego lepiej użyć?Zatem, jeśli wcześniej mieliśmy kod:
something = 'lalala'
something2 = 'hey'
I zmienimy go na:
something := 'lalala' # BŁĄD
something2 = 'hey' # OK
Bo tak po prostu jakoś nam się uwidzi, to kod taki nie zadziała. Nie ma zatem takiego miejsca, gdzie operator
:=
i=
byłyby jednocześnie poprawne. Zwykłe, tradycyjne przypisanie?=
. Miejsce, gdzie nie możesz użyć=
, czyli domyślnie wyrażenie?:=
. Prosta sprawa, nie inaczej.Nie będzie ich też można 'łączyć ze sobą.' Co to znaczy?
y = y1 := f(x) # BŁĄD
Taki zapis nie przejdzie. Ponownie byłoby to niepotrzebne, mylące i zbędne. Nie chcemy redundancji w Pythonie. Wszystko ma być czytelne, dlatego też taką operację można zastąpić następującym zapisem:
y = (y1 := f(x)) # OK
Innym tego przykładem mogło by być:
bar(x = y := f(x)) # BŁĄD
bar(x = (y := f(x))) # OK
To również nie zadziała - bez nawiasów nie wolno używać przypisania w wyrażeniu jako wartości dla keyword-argument. Ponownie - żeby czytelność była.
Dyskusja toczy się, czy zapis poniżej powinien być dozwolony
foo(x=0, y := f(0))
bar(x := 0, y = f(x))
Czyli używanie keyword-arguments i przypisania w wyrażeniu jednocześnie w wywołaniu funkcji. Co z tego wyjdzie, to się okaże.
Przypisania w wyrażeniu nie będzie można też użyć podczas definiowania domyślnych wartości argumentów funkcji czy też w pośrednich jego wyrażeniach. Co to znaczy?
def foo(answer = p := 42): # BŁĄD
def bar(answer = (p := 42)): # BŁĄD
def baz(callback = (lambda arg: p := arg)): # BŁĄD
To chyba tyle, jeśli chodzi o główne przypadki gdzie można, a gdzie nie można będzie użyć
:=
. Oczywiście, to, że dana konstrukcja jest dozwolona, nie znaczy, że należy jej używać w każdym miejscu, gdyż większość z tych możliwości wymienionych wyżej, jest niepotrzebnie komplikującym elementem kodu i raczej nie powinno się ich tak wykorzystywać,:=
powinien byc używany tam, gdzie faktycznie uprości on kod, a nie wszędzie, bo to jakaś fajna nowinka technologiczna.# Różnice między dwoma operatorami
Różnice są widoczne chociażby wtedy, kiedy chcemy przypisać wartości do wielu zmiennych jednocześnie. Jak to wygląda?
x = y = z = 0
(x := (y := (z := 0)))
Bardzo brzydki konstrukt, racja?
Przypsanie w wyrażeniu może być tylko w postaci
NAME := exp
, to znaczy, że takie operacje jak:x[0] = 0
someobj.prop1 = 'something'
Nie będą wspierane przez
NAME := exp
.Podobnie
+=
,-=
,*=
itd. również nie zadziała podczas używania:=
.x += y
Trzeba będzie to zrobić tak:
(x := x + y)
# Podsumowanie
Nowego operatora przypisania w wyrażeniu, będzie można użyć do *uproszczania list comprehensions, zapisywania wartości warunków czy innych wyrażeń.*
Oczywiście nic nie jest jeszcze pewne, wciąż prowadzi się dyskusje na temat tego, jak to wszystko ma wyglądać i działać, zmienić się może nawet sam operator, bo rozważane, zamiast
:=
, są jeszczeas
albo->
itd., ale taki mniej więcej będzie tego obraz.Artykuł można przeczytać też na moim blogu, o tutaj. O tyle tam ładniej, że kolorowanie składni jest.
Albo na steemit, tu, jeśli ktoś korzysta.
#programowanie #mlodyprogramuje #python
@11001100110O11: No nie bardzo. Async i await są od pythona 3.5, teraz po prostu zostały w końcu zarezerwowanymi słowami kluczowymi.
https://www.python.org/dev/peps/pep-0492/
ale to jest masakrycznie nieczytelne.
filtered_data = [ (y := f(x)) for x in data if y is not None]
jest dość czytelne i przyjazne a jest to kolejna z dozwolonych form
po prostu kwestia tego, jak my to napiszemy, jak akurat podałem przykłady głównie z pepa
y
, czyf(x)
, czy co innego jeszcze.@KrzaQ2: Też mi się tak wydawało i zajrzałem do tego PEP, i tam sa lepsze przykłady, np.:
if match := re.search(pat, text):
_____print("Found:", match.group(0))
jest oczywiście przykład is not None, ale mnie on od razu raził w oczy i pewnie zapis:
filtered_data = [y for x in data if
[y := f(x) for x in data if y]
- to bym rozumiał. To co jest teraz to jakaś podwójna definicjay
.