Bu işaret ne işe yarıyor: "->"?

Merhaba,

Arkadaşlar, internette araştırdım ama bir şey bulamadım.

Bu işaretin ne işe yaradığını ve nasıl kullanıldığı hakkında fikri olan varmı?

Merhaba,

Bu işaret, fonksiyonlardan dönen verinin tipinin belirtilmesine yarıyor. Kullanma zorunluluğu veya koda herhangi bir etkisi yok.

def f(x: int) -> int:
    return x ** 2
1 Beğeni

Yani, bu ikisi işlevsellik açısından aynı:

def f(x: int) -> int:
    return x ** 2
def f(x): # -> int
    return x ** 2

Öyle mi?

İkisinin de herhangi bir etkisi yok. Ancak okuyan kişi, ilk koda baktığı zaman, bu fonksiyonun int tipinde bir veri döndürdüğünü -şayet bu ifadenin ne anlama geldiğini biliyorsa- anlar. İkinci koddaki yorum satırı ise, fonksiyondan int tipinde bir veri döndüğüne yönelik bir anlam verebilir de/vermeyebilir de. Bu yorumun ne anlama geldiği kimin nasıl yorumladığına bağlı olarak değişir.

Hmm… Python’un ilginç bir özelliği.

Ben de ilk bakışta, fonksiyona verilebilecek veri türlerini filtreliyor ve döndürülen değerlerin türünü ayarlıyor sanmıştım. :confused:

Teşekkür ederim. :slight_smile:

Python’da bir fonksiyonun argümanlarının tipleri açıkça tanımlanmış olsalar bile, bu tipler dışında başka tipler de argüman olarak verilebilir ve Python bu durumda hiç bir uyarı veya hata vermez. Hata ancak verilen argümanın tipi, fonksiyondaki işlemlere uygun olmadığında, çalıştırılma zamanında ortaya çıkar ve bir AttributeError hatası yükseltilir.

1 Beğeni

Okuyan programcıların yanı sıra bazı teknolojilerin de daha doğru sonuçlar vermesini sağlıyor. Çoğu python editorü tipe göre kod tamamlaması öneriyor veya istenilen tipe uymayan bir değer girildiğinde sizi uyarıyor.

2 Beğeni

bir de mypy var

Hocamızın değindiği bu “açığı” mypy ile kapatabiliyorlar, uyarı veya hata alabiliyoruz

2 Beğeni

Bu arada parametre tiplerini ayrıntılı olarak belirtmek için typing kütüphanesi incelenebilir.

3 Beğeni

Bende içimden: “Acaba, PSF’ye geribildirim göndersek dile eklerlermi?” diyordum;

Birileri çoktan yapmış bile :slight_smile:

Tip belirtimlerinin kodun çalışma şekline bizzat etkisi yok ama fonksiyonların niteliklerinde saklanıyorlar, istersek kullanabiliriz:

import inspect

def get_function_annotations(f):
    sig = inspect.signature(f)
    return sig.return_annotation, sig.parameters

class AnnotationError(ValueError): pass

def check(f):
    if not __debug__: return f
    
    return_type, paramater_types = get_function_annotations(f)
    if return_type == inspect._empty:
        raise AnnotationError(f"return type is untyped.")
        
    for name, tp in paramater_types.items():
        if tp.annotation == inspect._empty:
            raise AnnotationError(f"Parameter {name!r} is untyped.")
    
    def checker(*args):
        for i, (name, tp) in zip(args, paramater_types.items()):
            if not isinstance(i, tp.annotation):
                raise ValueError(f"Expeted parameter {name!r} of function <{f.__qualname__}> to be an instance of {tp.annotation}, found {type(i)}")

        r = f(*args)
        if not isinstance(r, return_type):
            raise RuntimeError(f"Expected function <{f.__qualname__}> to return a {return_type}, not {type(r)}.")
        return r

    checker.__name__ = f.__name__
    checker.__qualname__ = f.__qualname__
    checker.__doc__ = f.__doc__
    
    return checker

@check
def f(b: str, i: int) -> str:
    return b * i

f("", 1) # çalışıyor
f(1,  1) # hata

Hatta bunun yapılmışı var:

2 Beğeni

Konu çözülmüş zaten ama bir ekleme yapmak isterim. C#, Java vb. dillerde tip tanımlaması yapılır ve bir uyuşmazlık çıkarsa hata alırsınız. Fonksiyonunuz bir şey döndürmüyorsa bile bir şey dönmediğini belirtmek için fonksiyonu tanımlarken başına void (boş) terimini eklersiniz. Python’da bu zorunlu değil ve önceden böyle bir şey yapamıyorduk sanırım -veya ben bilmiyordum-. Gayet kullanışlı bir özellik kullanılmadığında sorun teşkil etmemesi özgür kılıyor.

Bi zamanlar, merak edip örnek Java kodlarına baktığımda o, void ifadesine sıkça rastlamıştım ama hiçbir şey anlamamıştım -zaten o yüzden Python öğrendim :slight_smile:-


:thinking: Python’da böyle bir şey yok ki?

Yoksa, yukarıdaki modüllerden birinden mi bahsediyorsunuz?

Burada aslında bir tip tanımlama yapmış oldunuz. Direkt örnek vereyim. Aşağıdaki c# ve python fonksiyonları aynı şeyi yapıyor.

#python
def tam_sayi_dondur() -> int:
    a = 5
    return a
//C#
int tam_sayi_dondur(){
    int a = 5;
    return a;
}

Gördüğünüz gibi c# fonksiyonunda void yerine int terimini kullandık. Eğer void yazsaydık int yerine,
c# bize hata verecekti. Çünkü int bir değer döndürdüğümüz halde fonksiyonun hiçbir değer döndürmemesi gerektiğini söyledik. Aşağıda bunun bir örneği var:

/*Bu fonksiyon hata verecek çünkü int değer döndürdüğümüz halde
void terimiyle oluşturduk fonksiyonu.
*/
void tam_sayi_dondur(){
    int a = 5;
    return a;
}

Ama python’da böyle bir sorunumuz yok. Yani tip tanımlaması yapıp yapmamamız önemli değil.
Aşağıdaki gibi:

# Tip tanımlaması yaptık. Sorunsuz çalışır.
def tam_sayi_dondur() -> int:
    a = 5
    return a

# Tip tanımlaması yapmadık. Ama yine de sorunsuz çalışır.
def tam_sayi_dondur():
    a = 5
    return a

Kısaca c#'da tip tanımlaması yaparken void yerine döndüreceğimiz değerin tipini yazıyoruz ve bu zorunlu bir şey. Python’da void diye bir terim yok bunun yerine → işaretini kullanıyoruz. Bu zorunlu değil. İstersek tip tanımlaması yapmadan da fonksiyonu oluşturabiliyoruz. Bir şey döndürmeyeceksek de herhangi bir şey yazmamıza gerek yok.

1 Beğeni