Fonksiyonun içindeki listeyi global olarak kullanamıyorum


sıkıntım, mesela 2 tane isim numara ekledim ve listele dedim buraya kadar sıkıntı yok… sonra tekrardan numara ekleyip listele dediğimde son eklediklerimi göstermiyor…

Çünkü fonksiyonu çağırdığınızda, rehber listesi sıfırlanır. Yani siz rehber listesini global alanda aslında a'ya eşitliyorsunuz. a'nın içinde eklemiş olduğunuz kayıtlar var. Ama kayıt_ekle fonksiyonunu bir kez daha çağırırsanız, bu sefer ilk başta boş bir rehber listesi tanımlanır, a'da olan kayıtlar a'da kalır. Bu boş listeye sıfırdan kayıt eklemek zorunda kalırsınız. Ve programı kapatınca bu kayıtlar da silinir.

1 Beğeni

evet doğru söylüyorsunuz peki ne yapmam gerekiyor… rehberi global olarak tanımlayınca da hata alıyorum…amacım sizin de anladığınız üzere bi rehber oluşturmak…

Bu rehberi program kapandıktan sonra da kullanmak istiyorsanız sqlite gibi bir kütüphane kullanmanız gerekiyor.

rehber'i bir parametre haline getirin ve listenizi parametre olarak yollayın.

Kodlarınızı da fotoğraf olarak atmayın lütfen, ``` arasına alarak atın.

1 Beğeni

Yani liste fonksiyon içerisinde sürekli sıfırdan tanımlanmasın bunun yerine onu bir parametre haline getirin. Fonksiyonu her çağırdığınızda bu rehberi tekrar tekrar parametre olarak yazarsınız.

def kayit_ekle(rehber: list = []):
    # rehberle ilgili işlemler
    # rehberi return etmenize gerek yok.

rehberim = [...]
kayit_ekle(rehberim)
kayit_ekle(rehberim)

Böylece rehberin eleman sayısı sürekli artar.

rehber'i ön tanımlı yapmak sıkıntılı, listeler mutable. Ayrıca anlamsız da, değer döndürmüyoruz çünkü.

Nasıl bir sıkıntısı var acaba? Parametre değerini ön tanımlı olarak yazmanın belli bir kuralı var mı? Yani değer dönecekse ön-tanımlı olmalı şeklinde bir kural mı var?

def kayıt_ekle():

    while True:
        isim=input("isim giriniz(çıkış yapmak için (çıkış) yazınız : ")
        if isim=="çıkış":
            break
        soyad=input("soyad giriniz: ")
        numara=int(input("numara giriniz: "))
        sure=input("eklemek istediğinizden emin misiniz (evet,hayır): " )
        if sure.upper().startswith("E"):
            print("kayıt başarılı")
            rehber+=[[isim,soyad,numara]]
            print(rehber)

    return rehber

a=kayıt_ekle()

def kayıt_listele():
    x=0
    for i,j,k in rehber:
        x+=1
        print(str(x)+") isim--> {}  soyad--> {}   numarası--> {}".format(i,j,k))

def kayıt_ara():
    while True:
        isim=input("kimi bulmak istiyorsun isim veya soyad gir: ")
        for i in a:
            if isim in i:
                for j in i:
                    print(j)
        print("kayıt bulunamadı kontrol ediniz")
        y=input("çıkış için çıkış yazınız: ")
        if y=="çıkış":
            break


while True:
    a=int(input("""
    1) kayıt ekle
    2) kayıtları listele
    3) kayıt ara
    4) kayıt sil
    5) çıkış
        seçenek(1-5)
    """))
    if a==1:
        fonksiyonlar.kayıt_ekle()
    elif a==2:
        fonksiyonlar.kayıt_listele()
    elif a==3:
        fonksiyonlar.kayıt_ara()

kodun tamamı bu…

1 Beğeni

Listeler mutable olduğu için rehber hep aynı nesneye işaret ediyor, yani fonksiyonu her -parametresiz- çağırışımızda aynı listeyi büyütüp durmuş oluyoruz. Hem bu listeye fonksiyon dışından erişemiyoruz, değer döndürülmüyor çünkü.

Ayrıca side effecti için çağıracağımız bir fonksiyonun üzerinde değişim yapacağı nesneyi parametre olarak vermeyip öntanımlı bir değer kullandırtmamız uygun olmaz diye düşünüyorum.

okunurluğu daha kolay olur diye o şekilde atmıştım

Daha kolay olmuyor, kodu ``` arasına alarak metin olarak atmanız herkes için iyi olur. Hem kodunuz üzerinde değişim yapıp bir şeyler de deneyebiliriz bu sayede.

bu arada bu prgorama başlayalı 1 buçuk hafta flan oldu onun için kod saçma gelebilir bildiklerimden birşeyler türetmeye çalıştım

rehber hep aynı nesneye mi işaret ediyor? Siz rehberin yerine ne yazarsanız ona işaret eder. @Baris_UNLU, listenin tekrar tekrar tanımlanmasının önüne geçmek istemiyor muydu zaten?

def f(rehber: list = []):
    rehber.append(input())
    
    
    
a = []
b = []
f(a)
print(a)
f(b)
print(b)

Burada rehberi hep aynı liste için kullanmıyoruz ki, değişik listeler için de aynı işlevi görsün diye kullanıyoruz. Değer döndürmesine gerek yok, çünkü global alandaki bir listeyi alıyor ve içine eleman ekliyor. Liste zaten fonksiyon dışında tanımlı, fonksiyonda üstünde işlem yapılıyor ve sonradan listenin eleman sayısı değişmiş olarak çıkıyor.

Argümanın ön-tanımlı olmasının veya olmamasının fonksiyonu çağırırken argüman olarak yazacağımız liste üzerinde herhangi bir etkisi yok ki. Ön-tanım kısmını kaldırın gene aynı işlem yapılır.

def f(rehber):
    rehber.append("hello")
def f(rehber: list = []):
    rehber.append("hello")

Her iki fonksiyon şayet f’e parametre vererek çağırırsak aynı işlemi yapacak. Parametre vermeden çağırırsak veya isimsiz bir parametre verirsek sıkıntı oluşur.

def f(rehber: list = []):
    rehber.append("hello")
    
    
f(["merhaba"]) # isimsiz parametre
print(rehber)

"""
Traceback (most recent call last):
  File "./a.py", line 10, in <module>
    print(rehber)
NameError: name 'rehber' is not defined
"""

a'yı iki kere tanımlıyorsunuz ama. ya fonksiyondan dönen değeri atadığınız a listesinin ismini ya da a=int(input... kısmında yer alan a'nın ismini değiştirmeniz gerekiyor. Ayrıca fonksiyonlar nereden geliyor? Bunları bir modüle koyup import mu ediyorsunuz?

Parametre yollamazsak, evet. Eksik anlatmışım.

Evet zaten bu soruna çözüm olarak kullandığımız yöntem. Yani fonksiyonun anlamlı olması için dışarıdan bir nesne vermemiz lazım, o zaman neden bu parametreye ön tanımlı bir değer veriyoruz? Ön tanımlı değer kullanıcının parametreyi vermemesinin yolunu açıyor, bunun uygun bir tasarım olmadığını düşündüğümü söylemiştim:


Bence de yok. Peki biz bu fonksiyonu hep parametre vererek kullanacaksak niçin parametrenin bir ön tanımlı değeri var?

Eğer parametreyi dışarıdan paslarsak aynı iş yapılır, bir de paslamamayı deneyelim:

def f(p = []):
    print(f"{p=}")
    print("p'nin ID'si:", id(p))
    p.append(1)

f()
f()
f()

Yukarıdaki kodda görülen etkiden dolayı bunu demiştim:


Bulunduğumuz scope’da olmayan bir değişkeni kullanmaya çalışmamızdan dolayı hata alıyoruz, ve bu benim en başta dediğim şeyi destekliyor gibi duruyor. Parametre vermeden kullanmanın anlamsız olduğu bir fonksiyonunun bu parametresi niye ön tanımlı bir değere sahip?

Evet, benim demek istediğim de buydu.

Bende alışkanlık oldu bu ön-tanımlı değerleri vermek. Sebebi sadece bu.

Dediğim gibi bu benim alışkanlığım oldu. Ön-tanımlı değere ihtiyaç duyulmayacağı zaman bile kullanıyorum. Başka bir açıklaması da yok.

Kodlarınızı şu şekilde değiştirebilirsiniz.

def kayıt_ekle(rehber):
    while True:
        isim=input("isim giriniz(çıkış yapmak için (çıkış) yazınız : ")
        if isim=="çıkış":
            break
        soyad=input("soyad giriniz: ")
        numara=int(input("numara giriniz: "))
        sure=input("eklemek istediğinizden emin misiniz (evet,hayır): " )
        if sure.upper().startswith("E"):
            print("kayıt başarılı")
            rehber.append([isim,soyad,numara])


rehber = []
kayıt_ekle(rehber)

def kayıt_listele(rehber):
    x=0
    for i,j,k in rehber:
        x+=1
        print(str(x)+") isim--> {}  soyad--> {}   numarası--> {}".format(i,j,k))

def kayıt_ara(rehber):
    while True:
        isim=input("kimi bulmak istiyorsun isim veya soyad gir: ")
        for i in rehber:
            if isim in i:
                for j in i:
                    print(j)
        print("kayıt bulunamadı kontrol ediniz")
        y=input("çıkış için çıkış yazınız: ")
        if y=="çıkış":
            break


while True:
    a=int(input("""
    1) kayıt ekle
    2) kayıtları listele
    3) kayıt ara
    4) kayıt sil
    5) çıkış
        seçenek(1-5)
    """))
    if a==1:
        kayıt_ekle(rehber)
    elif a==2:
        kayıt_listele(rehber)
    elif a==3:
        kayıt_ara(rehber)
3 Beğeni

yardımlarınız için teşekkürler dediğim gibi yeni başladım bu programlama olayına kullandığınız çoğu terimi anlamıyorum bile ben biraz daha videolar flan izleyip yazayım buraya :slight_smile:

@EkremDincel, yanlış birşey söylemiyor. Sadece ihtiyaç duyulmadığı halde fonksiyon parametresi için neden ön-tanımlı değer kullandığımı sordu, ben de bunun bir ihtiyaç olmadığını ama bir alışkanlık olduğunu söyledim.

1 Beğeni