Python'da fonksiyon içinde listeyi yeniden atama

4nd1z

Decapat
Katılım
25 Kasım 2021
Mesajlar
115
Daha fazla  
Cinsiyet
Erkek
Merhabalar, Python'da bir listedeki tüm sayıları (int olanları) [listenin içinde başka listeler de olsa onların içindekini de toplayan] toplayan bir fonksiyon yazmaya çalışıyorum ama karşıma nasıl çözeceğime beynimin yetmediği sorunlardan bahsedeyim:
1)
[CODE lang="python" highlight="8"]
def ic_ice_toplam(v):
bos=[]
for eleman in v:
if isinstance(v,str):
continue
elif isinstance(eleman,list):
ic_ice_toplam(eleman)
elif isinstance(eleman,int):
bos.append(eleman)
return sum(bos)[/CODE]
Burada gördüğünüz gibi bos adlı listeyi fonksiyon içinde tanımladığımda 8. satırdaki iç içe fonksiyonu devreye girince fonksiyon her açıldığında bos listesini sıfırladığından bir işe yaramıyor. Bunu çözmek için bos adlı listeyi fonksiyonun dışında tanımladığımda ise fonksiyon çalıştıktan sonra çıkan değer bos'un içine kaydedildiğinden dolayı fonksiyon sonraki çalışmalarında o değeri de toplamın üstüne ekliyor.
bunu çözmek için ise şunu yapmayı denedim:
Python:
bos=[]
def ic_ice_toplam(v):
    # bos=[]
    for eleman in v:
        if isinstance(v,str):
            continue
        elif isinstance(eleman,list):
            ic_ice_toplam(eleman)
        elif isinstance(eleman,int):
            bos.append(eleman)
    else:
        bos1=bos[::]
        bos=[]

    return sum(bos1)
bunu yapıp denediğimde fonksiyonu tanımlarken sorun çıkmıyor ama fonksiyonu bir yerde çağırdığımda bana bos.append(eleman) yazılı kodu göstererek şu hatayı veriyor: "UnboundLocalError: local variable 'bos' referenced before assignment"
bunu nasıl çözebilirim yani fonksiyon her çalışmasından sonra bos adlı listeyi nasıl sıfırlattırabilirim?
 
Son düzenleyen: Moderatör:
Son 1 hafta içinde bunu bir yerde gördüm ve çözümü tam hatırlamıyorum ama none olarak atanmış parametre olarak alıp none ise boş liste şeklinde atama yapıyordu diye aklımda kalmış. Dener misiniz?

Kod:
def ic_ice_toplam(v, bos=None):
    if bos is None:
        bos = []
    for eleman in v:
        if isinstance(v, str):
            continue
        elif isinstance(eleman, list):
            ic_ice_toplam(eleman)
        elif isinstance(eleman, int):
            bos.append(eleman)
    return sum(bos)
 
Yerel değişkenler scope sonunda silinir, problemine gelirsek fonksiyon kendini tekrar çağırıyor ancak döndürdüğü değeri işleme sokmuyorsun, şöyle çalışması gerek.

Python:
def ic_ice_toplam(v):
    bos=[]
    temp = 0
    for eleman in v:
        if isinstance(v,str):
            continue
        elif isinstance(eleman,list):
            temp = ic_ice_toplam(eleman)
        elif isinstance(eleman,int):
            bos.append(eleman)
    return sum(bos) + temp
 
b
Son 1 hafta içinde bunu bir yerde gördüm ve çözümü tam hatırlamıyorum ama none olarak atanmış parametre olarak alıp none ise boş liste şeklinde atama yapıyordu diye aklımda kalmış. Dener misiniz?

Kod:
def ic_ice_toplam(v, bos=None):
    if bos is None:
        bos = []
    for eleman in v:
        if isinstance(v, str):
            continue
        elif isinstance(eleman, list):
            ic_ice_toplam(eleman)
        elif isinstance(eleman, int):
            bos.append(eleman)
    return sum(bos)
bu fonksiyon ise sadece içindeki sayıları topluyor, başka bir listeyle karşılaşınca yokmuş gibi davranıyor mesela [[1, 2], 3, 4 ] ün sonucunu 7 buluyor maalesef
Yerel değişkenler scope sonunda silinir, problemine gelirsek fonksiyon kendini tekrar çağırıyor ancak döndürdüğü değeri işleme sokmuyorsun, şöyle çalışması gerek.

Python:
def ic_ice_toplam(v):
    bos=[]
    temp = 0
    for eleman in v:
        if isinstance(v,str):
            continue
        elif isinstance(eleman,list):
            temp = ic_ice_toplam(eleman)
        elif isinstance(eleman,int):
            bos.append(eleman)
    return sum(bos) + temp
hocam bu sorunsuz çalıştı ama temp= 0 ı sonra temp=ic_ice_toplam(eleman) ve returndeki toplama olayını anlayamadım
Son 1 hafta içinde bunu bir yerde gördüm ve çözümü tam hatırlamıyorum ama none olarak atanmış parametre olarak alıp none ise boş liste şeklinde atama yapıyordu diye aklımda kalmış. Dener misiniz?

Kod:
def ic_ice_toplam(v, bos=None):
    if bos is None:
        bos = []
    for eleman in v:
        if isinstance(v, str):
            continue
        elif isinstance(eleman, list):
            ic_ice_toplam(eleman)
        elif isinstance(eleman, int):
            bos.append(eleman)
    return sum(bos)
hocam hatayı düzeltmek için 8. satırdaki kodu ic_ice_toplam(eleman,bos) yaptım 2. parametre kısmı boş kalmasın diye. oraya tekrardan bos yazmamın acaba başka bir şeyleri değişip değiştirmediğini bilmiyorum ama onu düzeltince sizinki de sorunsuz bir şekilde çalışmaya başladı
 
Son düzenleme:
Temp= 0'ı sonra temp = ic_ice_toplam(eleman) ve returndeki toplama olayını anlayamadım

İsinstance kullanım olarak Type'a benziyor.

Şimdi kodu Türkçeye çevirip okursak:
7. satırda şunu diyor: For döngüsünde tanımlanan eleman değişkeni eğer bir liste(array) türünde bir arguman alıyor ise bunu (sonrası 8. satır için) temp adında bir değişkene atıyor ve for döngüsünde kullanılan eleman değişkenini parametre olarak veriyor bu da sizin istediğiniz şey olmuş oluyor.

9. satırda fonksiyonun parametresine yazılan arguman bir tam sayı(array şeklinde veya tuple biçiminde ise)
Bunu fonksiyonun en başındaki bos adlı listeye ekliyor.(tam sayıları ekliyor)

Return yani fonksiyonun değer döndürme kısmında sum, listedeki elemanların(bunlar sayılar tabii ki) toplamını döndürüyor. Bu toplam sonucu ile de temp değişkeninin en son değeri ile topluyor.




Yanlışlarım varsa düzeltebilirsiniz
"UnboundLocalError: local variable 'bos' referenced before assignment"
Bu hatanın sebebi de bos adıyla tanımladığınız değişkenin global alanda olmasından dolayı. Yani fonksiyonun dışında başta tanımladığınız bir değişkeni fonksiyonun içerisinde her hangi bir değişikliğe uğratacaksanız onu aynı fonksiyonun içinde ilk satırına global anahtar kelimesi
yazıp boşluk bırakarak ilgili değişken adını yazmalısınız
Python:
bos = []
def fonksiyon(v):
    global bos
    for i in v:
        .
        .
        .
 
Son düzenleme:
Bence tek fonksiyonda cozmeye calismaya gerek yok.
Once esas listeyi flatten edersin, sonra da toplarsin icindeki elemanlari.
Toplama islemi degisme ozelligi tasidigindan reduce edebilirsin sonrasinda.

[CODE lang="python" title="flatten -> reduce"]from functools import reduce


def flatten(ls):
flattened = []
for e in ls:
if isinstance(e, list):
flattened.extend(flatten(e))
else:
flattened.append(e)
return flattened


def reduction(x, y):
x_int = isinstance(x, int)
y_int = isinstance(y, int)
if x_int and y_int:
return x + y
elif x_int:
return x
elif y_int:
return y
else:
return 0


het_list = [1, 2, 3, "a", "b", ["x", "y"], 5, [1, "p", 2, 3], "q", True, ["k", ["p", [1]]]]
print(reduce(reduction, flatten(het_list), 0))
[/CODE]

Daha kisa bir cozum de flatten -> filter -> sum olabilir.

[CODE lang="python" title="flatten -> filter -> sum"]def flatten(ls):
flattened = []
for e in ls:
if isinstance(e, list):
flattened.extend(flatten(e))
else:
flattened.append(e)
return flattened


def predicate(x):
return isinstance(x, int)


het_list = [1, 2, 3, "a", "b", ["x", "y"], 5, [1, "p", 2, 3], "q", True, ["k", ["p", [1]]]]
print(sum(filter(predicate, flatten(het_list))))
[/CODE]
 
Son düzenleme:
İsinstance kullanım olarak Type'a benziyor.

Şimdi kodu Türkçeye çevirip okursak:
7. satırda şunu diyor: For döngüsünde tanımlanan eleman değişkeni eğer bir liste(array) türünde bir arguman alıyor ise bunu (sonrası 8. satır için) temp adında bir değişkene atıyor ve for döngüsünde kullanılan eleman değişkenini parametre olarak veriyor bu da sizin istediğiniz şey olmuş oluyor.

9. satırda fonksiyonun parametresine yazılan arguman bir tam sayı(array şeklinde veya tuple biçiminde ise)
Bunu fonksiyonun en başındaki bos adlı listeye ekliyor.(tam sayıları ekliyor)

Return yani fonksiyonun değer döndürme kısmında sum, listedeki elemanların(bunlar sayılar tabii ki) toplamını döndürüyor. Bu toplam sonucu ile de temp değişkeninin en son değeri ile topluyor.




Yanlışlarım varsa düzeltebilirsiniz

Bu hatanın sebebi de bos adıyla tanımladığınız değişkenin global alanda olmasından dolayı. Yani fonksiyonun dışında başta tanımladığınız bir değişkeni fonksiyonun içerisinde her hangi bir değişikliğe uğratacaksanız onu aynı fonksiyonun içinde ilk satırına global anahtar kelimesi
yazıp boşluk bırakarak ilgili değişken adını yazmalısınız
Python:
bos = []
def fonksiyon(v):
    global bos
    for i in v:
        .
        .
        .
Haklısnız şimdi kafama oturdu, global olayını hocam anlatmıştı da tamamen aklımdan çıkmış sayenizde hatırladım. Çok teşekkür ederim.
Bence tek fonksiyonda cozmeye calismaya gerek yok.
Once esas listeyi flatten edersin, sonra da toplarsin icindeki elemanlari.
Toplama islemi degisme ozelligi tasidigindan reduce edebilirsin sonrasinda.

[CODE lang="python" title="flatten -> reduce"]from functools import reduce


def flatten(ls):
flattened = []
for e in ls:
if isinstance(e, list):
flattened.extend(flatten(e))
else:
flattened.append(e)
return flattened


def reduction(x, y):
x_int = isinstance(x, int)
y_int = isinstance(y, int)
if x_int and y_int:
return x + y
elif x_int:
return x
elif y_int:
return y
else:
return 0


het_list = [1, 2, 3, "a", "b", ["x", "y"], 5, [1, "p", 2, 3], "q", True, ["k", ["p", [1]]]]
print(reduce(reduction, flatten(het_list), 0))
[/CODE]

Daha kisa bir cozum de flatten -> filter -> sum olabilir.

[CODE lang="python" title="flatten -> filter -> sum"]def flatten(ls):
flattened = []
for e in ls:
if isinstance(e, list):
flattened.extend(flatten(e))
else:
flattened.append(e)
return flattened


def predicate(x):
return isinstance(x, int)


het_list = [1, 2, 3, "a", "b", ["x", "y"], 5, [1, "p", 2, 3], "q", True, ["k", ["p", [1]]]]
print(sum(filter(predicate, flatten(het_list))))
[/CODE]
Hocam yanıtınız için teşekkür ederim, sayenizde filter ve reduce adlı yapıların olduğunu öğrendim en kısa zamanda bunları da öğrenmem için fırsat oluşturdunuz.
 
Bu durumda aşağıdaki koddaki her print ifadesinin aynı şeyi yazmasını bekleriz değil mi?

Onun pek de local scope variable olduğunu söyleyemem, zira scope sonunda işaret ettiği bellek silinmez, dışarıdan erişilebilir, adresi iletilebilir vs. Gerçi python bizim normal programlama anlayışımızdan çok farklı çalışıyor ancak kabaca yorumlarsak böyle.

Python:
def a(b=[]):
    b.append("a")
    return b

print(a())
print(a())
print(a())

liste = a.__defaults__[0]
liste.append("c")
liste.append("d")

print( a() )

hocam bu sorunsuz çalıştı ama temp= 0 ı sonra temp=ic_ice_toplam(eleman) ve returndeki toplama olayını anlayamadım
Fonksiyon kendini çağırıyorsa her birinin kendi yerel değişkenleri olur, her biri kendi içinde işlemleri yapar ve geri bir değer döndürür bu değeri de toplayarak geri döndürüyoruz ki ilk fonksiyon çağrısına geldiğimizde iç içe çağırdığımız fonksiyonların değerlerini de iletebilelim.

hocam hatayı düzeltmek için 8. satırdaki kodu ic_ice_toplam(eleman,bos) yaptım 2. parametre kısmı boş kalmasın diye. oraya tekrardan bos yazmamın acaba başka bir şeyleri değişip değiştirmediğini bilmiyorum ama onu düzeltince sizinki de sorunsuz bir şekilde çalışmaya başladı
Arkadaşın verdiği örnekte default parametreye list gibi referans mantığıyla (mutable)çalışan bir nesne eklersen ya da direk global bir nesne tanımlarsan bunlara recursive çağrılan bütün fonksiyonlardan erişirsin, çünkü hem bellek adresi iletilir hem de fonksiyon scope'unundan bağımsız olduğu için bellekte işgal ettiği yer temizlenmez.
 
Onun pek de local scope variable olduğunu söyleyemem, zira scope sonunda işaret ettiği bellek silinmez, dışarıdan erişilebilir, adresi iletilebilir vs. Gerçi python bizim normal programlama anlayışımızdan çok farklı çalışıyor ancak kabaca yorumlarsak böyle.

Python:
def a(b=[]):
    b.append("a")
    return b

print(a())
print(a())
print(a())

liste = a.__defaults__[0]
liste.append("c")
liste.append("d")

print( a() )


Fonksiyon kendini çağırıyorsa her birinin kendi yerel değişkenleri olur, her biri kendi içinde işlemleri yapar ve geri bir değer döndürür bu değeri de toplayarak geri döndürüyoruz ki ilk fonksiyon çağrısına geldiğimizde iç içe çağırdığımız fonksiyonların değerlerini de iletebilelim.


Arkadaşın verdiği örnekte default parametreye list gibi referans mantığıyla (mutable)çalışan bir nesne eklersen ya da direk global bir nesne tanımlarsan bunlara recursive çağrılan bütün fonksiyonlardan erişirsin, çünkü hem bellek adresi iletilir hem de fonksiyon scope'unundan bağımsız olduğu için bellekte işgal ettiği yer temizlenmez.
Tekrardan teşekkürler hocam anladım
 

Yeni konular

Geri
Yukarı