Tekil Mesaj gösterimi
Alt 10-02-2019 19:18  
  • Gbmdpof
  • AR-GE Tim
  • Üye Bilgileri
Üyelik tarihi
09/2016
Mesajlar
Konular

Teşekkür (Etti):
Teşekkür (Aldı):


Python 3.8 ile Gelecek Yeni Walrus Operatörü



Python 3.8'in ilk alpha sürümü (https://www.python.org/downloads/release/python-380a1/) 3 Şubat 2019'da yayınlandı ve burada karşımıza çıkan yeni özelliklerden biri de PEP 572 ile tanıtılan walrus operatörü.

Bu operatörün nasıl çalıştığını ve ne işe yaradığını önce PEP yazısından alınmış bir örnek verip ardından onun üzerinden giderek anlatmak daha kolay olur gibi:


Burada da görebileceğiniz gibi, hem değişken atayıp hem de bu atama ifadesinden bir dönen veri alabiliyoruz bu ifade ile.

Bu, gereksiz kod tekrarlarından kurtulup doğru kullanıldığında daha okunabilir bir kod yazmamızı sağlıyor.

Bunu kendimiz kullanmak için öncelikle Python 3.8'i kurmamız lazım. Ben bunun için pyenv kullanacağım. Kurulumu için bakabilirsiniz:

https://github.com/pyenv/pyenv#installation

Ardından aşağıdaki komut ile kurulumu yapıp onu varsayılan shell olarak belirleyebilirsiniz.

Kod:
λ pyenv install 3.8-dev 
Cloning https://github.com/python/cpython...
Installing Python-3.8-dev...
Installed Python-3.8-dev to /home/<usr>/.pyenv/versions/3.8-dev

λ pyenv shell 3.8-dev
λ python -V   
Python 3.8.0a1+
Gördüğünüz gibi artık varsayılan versiyon 3.8 oldu ve walrus operatörünü kullanabiliriz.

Örneğin basit bir örnek yazalım ve bunu walrus operatörü ile ve olmadan karşılaştıralım:

Walrus operatörü olmadan, bir siteden <p> tagleri arasındaki verileri çeken basit bir program:

Kod:
import re
import requests

pattern = re.compile('<p>(.*?)</p>')
r = requests.get('<url>')

results = pattern.findall(r.text)
if results:
    for result in results:
        print(result)
Walrus operatörü ile ise bir gereksiz satırdan kurtuluyoruz:
Kod:
import re
import requests

pattern = re.compile('<p>(.*?)</p>')
r = requests.get('<url>')

if results := pattern.findall(r.text):
    for result in results:
        print(result)
Ayrıca bunda belli olacağı gibi, scope o anki scope'tur. Eğer bu scope nonlocal veya global bir tanım içeriyorsa buna uyulur.

Bazı istisnalar

Parantez içine alınmamış ifadeler top level'da kullanılamaz, örneğin:

Kod:
y := f(x) # Geçersiz
(y := f(x)) # Geçerli ama önerilmez
Ayrıca atama ifadesinin sağ tarafında da parantez içine alınmadan kullanılamaz. Örneğin:

Kod:
y0 = y1 := f(x)  # Geçersiz
y0 = (y1 := f(x))  # Geçerli ama önerilmez
Yine parantezssiz kullanımlar fonksiyon çağırırken keyword argümanı ile kullanılamaz. Örneğin:

Kod:
foo(x = y := f(x))  # Geçersiz
foo(x=(y := f(x)))  # Geçerli ama kafa karıştıcı
Argümanların varsayılan değerlerini veya annotationlarını da parantezsiz kullanmak geçersiz olacaktır. Örneğin:

Kod:
def foo(answer = p := 42):  # Geçersiz
    ...
def foo(answer=(p := 42)):  # Geçerli, ama iyi bir stil değil
    ...

def foo(answer: p := 42 = 5):  # Geçersiz
    ...
def foo(answer: (p := 42) = 5):  # Geçerli, ama büyük ihtimalle işe yarar değil
    ...
Bu 4 istisnanın hepsi, = ve :='nin karıştırılması için olan istisnalar.

Ayrıca lambda fonksiyonlarında da paranteze alınmamış ifadeler kullanılamaz:

Kod:
(lambda: x := 1) # Geçersiz
lambda: (x := 1) # Geçerli, ama büyük ihtimalle işe yarar değil
(x := lambda: 1) # Geçerli
lambda line: (m := re.match(pattern, line)) and m.group(1) # Geçerli
Bu yeni özellik hakkında daha fazla için PEP sayfasına bakabilirsiniz: https://www.python.org/dev/peps/pep-0572/




___________________________________________

~humanity is overrated~
 Offline  
 
Alıntı ile Cevapla
 

wau