A409 Astronomide Sayısal Çözümleme
Transkript
A409 Astronomide Sayısal Çözümleme
AST415 Astronomide Sayısal Çözümleme - I 3. Döngü Yapıları, Listeler, Demet Değişkenler Bu derste neler öğreneceksiniz? ✔ Neden Döngülere İhtiyaç Duyarız? ✔ While Döngüleri ✗ Blok Kullanımı ✗ Matematiksel İşlemlerin Kısa Gösterimi (Örn. i += 1) ✗ Boolean İfadeler ✔ Listeler ✗ Listeler Üzerinde İşlemler ✔ For Döngüleri ✔ While ve For Döngüleri İle İşlemler ✔ Döngüler ve Listeler ✗ range ve xrange Fonksiyonları ✗ Listelerle Hızlı ve Kompakt İşlemler (List Comprehensions) ✗ İç İçe Listeler (Nested Lists) ✔ Demet (Tuple) Değişkenler Bir Dönüşüm Tablosu Örneği Bir liste halinde verilmiş bir grup sıcaklığı santigrad dereceden (ºC), fahrenheit dereceye (ºC) dönüştürmek istiyor olalım. -20.0 -15.0 -10.0 -5.0 +0.0 +5.0 10.0 15.0 20.0 30.0 35.0 40.0 -4.0 5.0 14.0 23.0 32.0 41.0 50.0 59.0 77.0 86.0 95.0 104.0 Basit Bir Çözüm C C C C C C C C C C C C C = = = = = = = = = = = = = -20; F = 9.0/5*C + 32; print C, F -15; F = 9.0/5*C + 32; print C, F -10; F = 9.0/5*C + 32; print C, F -5; F = 9.0/5*C + 32; print C, F 0; F = 9.0/5*C + 32; print C, F 5; F = 9.0/5*C + 32; print C, F 10; F = 9.0/5*C + 32; print C, F 15; F = 9.0/5*C + 32; print C, F 20; F = 9.0/5*C + 32; print C, F 25; F = 9.0/5*C + 32; print C, F 30; F = 9.0/5*C + 32; print C, F 35; F = 9.0/5*C + 32; print C, F 40; F = 9.0/5*C + 32; print C, F c2f_table_cirkin.py 'de verilen bu çözümün birkaç problemi var. Bunlar; 1. Çıktısının formatı çok çirkin! Ancak bu C ve F'yi doğrudan ekrana yazdırmak yerine daha önce öğrendiğimiz formatlama seçeneklerini kullanarak aşılabilir. 2. Asıl önemlisi, aynı ifadeyi defalarca yazıyor olmamız! Elimizin altında bir bilgisayar olduğuna göre bunu daha kolay yapabilmeliyiz. Tüm bilgisayar programala dillerinde olduğu gibi Python'da bunun çözümü döngü yapıları kullanmaktır. Python'da iki çeşit döngü yapısı bulunmaktadır: While döngüleri ve For döngüleri While Döngüleri While döngüsü verilen bir şart sağlanan kadar döngü yapısı içerisinde yer alan ifadeleri tekrar tekrar çalıştırır. Örnek: Amacımız verilen liste dahilinde C = -5 ºC'den başlayıp, C ≤ 40 ºC olduğu sürece 5 ºC'lik artışlarla sıcaklık değerini arttırıp, karşılık geldiği ºF 'yi hesaplamak ve her ikisini ekrana yazdırmak! Algoritma: C = -20 C ≤ 40 OLDUĞU SÜRECE aşağıdaki adımları TEKRARLA!: F = (9 / 5.) * C + 32 C ve F'yi ekrana yazdır C'yi 5 arttır Blok Kullanımı Döngü içerisinde çalışması istenen tüm ifadeler içeri doğru aynı miktarda bloklanmalıdır. Bunun miktarı önemli olmamakla birlikte, genel standart <TAB> ya da 4 boşluk kulllamaktır. print ’------------------’ # tablo basligi C = -20 # C icin baslangic degeri dC = 5 # dongu icinde C'nin arttirilacagi deger while C <= 40: # dongunun calismasi icin kosul F = (9.0/5)*C + 32 # Dongudeki ilk ifade print C, F # Dongudeki ikinci ifade C = C + dC # Dongudeki ucuncu ifade print ’------------------’ # Dongu sonrasi tablo sonu Bu kod segmentini IDLE'a yazıp (c2f_tablo_while.py) çalıştırmadan önce, kağıt kalemle her bir değişkenin her çalışma anındaki değerini yazın ve ekrana yazılacakları tahmin etmeye çalışınız. Daha sonra bu kodu çalıştırıp, aradaki (varsa) farkların nedenlerini anlamaya çalışın (Elle çalıştırmak → “trace” etmek). Programcılık öğrenirken ve kodunuzdaki olası hataları bulmaya çalışırken çok faydalı bir egzersizdir. İşlemlerin Kısa Gösterimi Bir değişken ismi, türüne göre (int, float, str gibi) yaratılan bir nesne (object) 'ye verilen bir isimdir. Değişkene yeni bir değer atadığınız vakit, yeni bir nesne yaratılır ve değişken ismi artık bu yeni nesnenin ismi olur. Bu nedenle matematiksel olarak yanlış gibi görünen aşağıdaki ifade bilgisayar bilimlerinde doğru bir atama ifadesidir. C = C + dC Bu ifadeyle C değişkenin atıfta bulunduğu tamsayı (int) nesnesinin değeri dC tamsayı (int) nesnesinin değeri kadar arttırılmakta, bu iki nesnenin ikisi birden tamsayı (int) değişkeni olduğu için yeni yaratılan nesne de tamsayı nesnesi olup, değeri de onların toplamı olmaktadır. C'nin daha önce atıfta bulunduğu nesne ise yok edimiş, C yeni yaratılan tamsayı nesnesinin ismi olmuştur. Bu ifade kısaca aşağıdaki şekilde de yazılabilir. C += dC Bu kısa gösterim diğer işlemler için de aynen kullanılabilir. C -= dC C *= dC C /= dC Karşılaştırma ve Mantıksal Operatörler Boolean İfadeler Boolean İfadeler: Sonucu DOĞRU (TRUE) ya da YANLIŞ (FALSE) olan ifadelerdir. George Boole, 1815-1864 Örnek 1: C == 40 C != 40 C >= 40 C <= 40 C > 40 C < 40 # # # # # # C C C C C C “eşittir” 40 “eşit değildir” 40 40'tan “büyük ya da ona eşittir” 40'tan “küçük ya da ona eşittir” 40'tan “büyüktür” 40'tan “küçüktür” Bu karşılaştırma operatörlerini yanı sıra mantıksal operatörler (not, and, or, xor) de Boolean ifadelerde kullanılıır. >>> x = 0; y = 1.2 >>> x >= 0 and y < 1 False >>> x >= 0 or y < 1 True >>> x > 0 or y > 1 True >>> x > 0 or not y > 1 False >>> -1 < x <= 0 # -1 < x and x <= 0 True >>> not (x > 0 or y > 0) False Python'da Listeler Python'a özel, elemanları rastgele seçilmiş değişken türleri olabilen dizi değişkenlerdir. Listenin herhangi eleman(lar)ı indeksleme yoluyla çağrılır. Listenin bir bölümünü alma işlemine dilimleme (ing. slicing) denir. >>> C = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40] >>> C[1] -15 >>> C[0] -20 >>> C[-1] 40 >>> C[0:2] [-20,-15] >>> C[-1:-3] [] >>> C[-3:-1] [30,35] >>> C[:] [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40] >>> C[:4] [-20, -15, -10, -5] >>> C[6:] [10, 15, 20, 25, 30, 35, 40] >>> C[:-3] [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25] Listeler Üzerinde İşlemler - I Herhangi bir listeye yeni bir eleman eklemek (append), çıkarmak (delete), istediğniz yere yerleştirmek (insert), herhangi bir elemanın indeksini bulmak gibi işlemleri yapabilmek için verilen fonksiyonları liste.fonksiyon_adi(arguman) yazarak gerçekleştirebilirsiniz. Bu şekilde kullanılan fonksiyonlara metot (ing. method, attribute) adı verilir. Aşağıda verilen metotlar liste nesnesinin metotlarıdır. >>> C = [-10, -5, 0, 5, 10, 15, 20, 25, 30] >>> C.append(35) # Listenin sonuna 35 sayisini ekler! >>> C [-10, -5, 0, 5, 10, 15, 20, 25, 30, 35] >>> C.insert(0,-15) # O. indekse -15 sayisini yerlestirir! >>> C [-15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35] >>> C.remove[10] # C listesinden 10 sayısını siler! >>> C [-15, -10, -5, 0, 5, 15, 20, 25, 30, 35] >>> len(C) # Listenin eleman sayisini verir1 10 >>> C.index(5) 3 İki listeyi ucuca eklemek için toplama işlemi kullanılır. Dikkat: Toplama işlemi verilen iki listenin elemanlarını birbiri ile toplamaz, bu listeleri ucuca ekler! >>> C = C + [40, 45] # C'nin sonuna [40, 45] ten oluşan listeyi ekler >>> C [-10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45] Listeler Üzerinde İşlemler - II Liste elemanlarına karşılık gelen yeni değişkenler yaratmak için kompakt bir yazım kuralı (syntax) bulunmaktadır. >>> birliste = [’adana’, ’kebap’, ’01’] >>> il, yemek, plaka = birliste >>> il ’adana' >>> yemek ’kebap’ >>> plaka ’01’ Bir listenin kopyasını oluşturmak için atama operatörü farklı bir şekilde kullanılır. >>> a = [1,2,3,4] >>> b = a >>> a[2] = 3.5 >>> b [1,2,3.5,4] >>> c = a[:] >>> a[3] = 4.5 >>> c [1,2,3.5,4] # a listesine bir baska isim verir # bu nedenle a listesi degisince b listesi degisir! # a listesinin elemanlarından olusan yeni bir liste # bu nedenle a listesi degisse de c listesi degismez For Döngüleri For döngüsü, döngü yapısı içerisinde yer alan ifadeleri önceden istenen kadar sayıda (defa) çalıştırır. Örnek: Amacımız verilen bir listenin tüm elemanlarını Fahrenheit dereceye çevirip ekrana yazdırmak olsun. Algoritma: C = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 30, 35, 40] Her bir C[index] elemanı için F = (9 / 5.) * C[index] + 32 C ve F'yi ekrana yazdır Bir sonraki elemana geç For Döngüleri Döngü içerisinde çalışmasıı istenen tüm ifadeler içeri doğru aynı miktarda bloklanmalıdır. Bunun miktarı önemli olmamakla birlikte, genel standart <TAB> ya da 4 boşluk kulllamaktır. print ’------------------’ # tablo basligi C = [-20, -15, -10, 0, 5, 10, 15, 20, 25, 30, 35, 40] for eleman in C: # C'deki her bir eleman icin F = (9.0/5)*eleman + 32 # Fahrenheit'e donusum yap print eleman, F # Ekrana yazdır print ’------------------’ # Dongu sonrasi tablo sonu Bu örnekte verilen tablo, yapısı itibarı ile tablo gibi düzenli görünmemektedir. Daha düzenli bir görünüm için aşağıdaki kod bloğunu (c2f_tablo_liste.py) kullanmak daha uygundur. print ’------------------’ # tablo basligi C = [-20, -15, -10, 0, 5, 10, 15, 20, 25, 30, 35, 40] print ’ C F’ for eleman in C: # C'deki her bir eleman icin F = (9.0/5)*eleman + 32 # Fahrenheit'e donusum yap print “%5d %5.1f” % (eleman, F) # Ekrana yazdır print ’------------------’ # Dongu sonrasi tablo sonu While ve For Döngüleri İle İşlemler - I Tüm for döngüleri en az bir while döngüsünü dönüştürülebilir. (Tersi doğru olmak zorunda değildir!) for eleman in liste_adi: islemler.. index = 0 while index < len(liste_adi): eleman = liste_adi[index] Islemler... Index += 1 print ’------------------’ # tablo basligi C = [-20, -15, -10, 0, 5, 10, 15, 20, 25, 30, 35, 40] indeks = 0 F = [] print ’ C F’ while indeks < len(C): # index degeri Cnin uzunlugundan kucuk # oldugu surece fahr = (9.0/5)*eleman + 32 # Fahrenheit'e donusum yap print “%5d %5.1f” % (eleman, fahr) # Ekrana yazdir F.append(fahr) # F dizinine hesaplanan degeri ekle indeks += 1 # indeksi bir arttir print ’------------------’ # Dongu sonrasi tablo sonu While ve For Döngüleri İle İşlemler – II range([baslangic],son,[adim]) Fonksiyonu range fonksiyonu özellikle for döngüleri ile sıkça kullanılan çok faydalı bir fonksiyondur. Yaptığı iş verilen başlangıç ve son değerleri arasında (son hariç!) istenen adım büyüklüğü dahilindeki tam sayılardan bir liste oluşturmaktır. range(n) → [0, 1, 2, 3, …, n-1] range(3, 27, 6) → [3, 9, 15, 21] range(2,8) → [2, 3, 4, 5, 6, 7] range(10, 2, -2) → [10, 8, 6, 4] print ’------------------’ # tablo basligi C = range(-20, 45, 5) # C listesini olustur F = [0.0]*len(C) # C listesiyle ayni uzunlukta sadece # sifirlardan olusan bir liste olustur for indeks in range(len(C)): # Cnin tum elemanlari icin F[indeks] = (9.0/5)*C[indeks] + 32 print ’------------------’ # Dongu sonrasi tablo sonu While ve For Döngüleri İle İşlemler – III Reel Sayı Adım Kullanmak range fonksiyonu sadece tam sayı (integer) üretir. Bu da başlangıç değeri ile son değer arasında hep tam sayı adım atmakla bizi kısıtlar. Adımlarımızın reel sayı olmasını istiyorsak bunu döngü yapısı içerisinde yapmamız gerekir. C_adim = 0.5 C_baslangic = -5 n = 16 C = [0.0]*n; F = [0.0]*n for i in range(n): C[i] = C_baslangic + i*C_adim F[i] = (9.0/5)*C[i] + 32 C_baslangic = -5; C_adim = 0.5; C_son = 20 cent = C_baslangic C = []; F = [] while cent <= C_son: C.append(cent) fahr = (9.0/5)*cent + 32 F.append(fahr) cent += C_adim Döngü İçerisinde Liste Elemanı Değiştirmek range fonksiyonu Bir liste içinde gezerken herhangi bir elemana geldiğimizde onu değiştirmek istiyor olalım. >>> C = range(-20,45,5) >>> for cent in C: ... cent += 5 İstedğimiz şey C'deki her elemanı 5 arttırmaktı ama istediğimizi yapamadık. Çünkü cent değişkeni bizi C'de sadece “gezdirir”, C'deki değerler üzerinde bir etkisi yoktur. İstediğimize aşağıdaki şekilde ulaşabiliriz. >>> C = range(-20,45,5) >>> for i in range(len(C)): ... C[i] += 5 Aslında bir döngü içerisinde rastlanan bir liste elemanının hem değerini hem de indeksini kullanmanın bir yolu var ama basit görünmekle birlikte biraz komplike bir yol! >>> C = range(-20,45,5) >>> for i, cent in enumerate(C): ... C[i] = cent + 5 Döngü İçerisinde Liste Elemanı Değiştirmek xrange fonksiyonu Temelde çok benzer işlevi (istediğiniz sıklıkta ve aralıkta tam sayılardan oluşan liste üretmek) olan bu iki fonksiyondan range fonksiyonu liste nesnesi döndürürken xrange fonksiyonu bir xrange nesnesi döndürür. Aralarındaki bu temel farkın getirdiği teknik fark xrange fonksiyonunu çok daha büyük listeler üretmek için daha kullanışlı ve daha az “hafıza canavarı” haline getirir. xrange fonksiyonu her çalıştığında herhangi bir liste indeksi için bir tam sayı ürettiği gerekçesiyle eğer aynı liste üzerinde birden fazla kez çalışılacaksa bunu range ile yapmak daha akılcıdır. >>> C = xrange(-20,45,5) >>> for i in xrange(len(C)): ... C[i] += 5 Tıpkı range gibi xrange’i de negatif sayılarla ve ters sırada liste oluşturmak için kullanabilirsiniz. Python 3.x ile birlikte xrange fonksiyonu kaldırılmıştır! >>> C = xrange(-20,45,5) >>> for i, cent in enumerate(C): ... print C[i] Listelerle Hızlı ve Kompakt İşlemler “List Comprehensions” Bir liste içinde gezerken her bir eleman için başka bir liste içerisinde yeni bir eleman yaratmak çok sık ihtiyaç duyulan bir özelliktir. Python bunun için “list comprehensions” adı verilen kompakt bir yazım kuralına sahiptir. >>> C = [-5 + i*0.5 for i in range(n)] >>> F = [(9.0/5)*cent + 32 for cent in C] >>> C_arti_5 = [cent + 5 for cent in C] Birden fazla (aynı uzunlukta) liste içinde aynı anda “gezebilmek” de mümkündür. >>> for i in range(len(C)): ... print ’%5d %5.1f’ % (C[i], F[i]) Bunun için de python'un güzel ve basit bir yazım kuralı bulunmaktadır (zip). >>> for cent, fahr in zip(C, F): ... print ’%5d %5.1f’ % (cent, fahr) İndeksler yerine liste elemanları kullanarak “gezmek” daha “Pythonik” 'tir. İç-içe Listeler (Nested Lists) Elemanlarından en az biri bir liste olan listeler de tanımlamak Python'nda mümkündür. >>> C = range(-20,41,5) >>> F = [(9.0/5)*cent + 32 for cent in C] >>> table1 = [C, F] >>> table1[0] [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40] >>> table1[0][2] -10 İç-içe Listeler (Nested Lists) Yapmak istediğimiz her bir elemanı bir liste olan yeni bir liste yerine, bir satırındaki birinci elemanını bir listeden, ikinciyi diğer listeden alan bir tablo oluşturmak ise izleyeceğimiz yol aşağıdaki gibi olmalıdır. >>> C = range(-20,41,5) >>> F = [(9.0/5)*cent + 32 for cent in C] >>> table2 = [] >>> for cent, fahr in zip(C, F): ... table2.append([cent,fahr]) >>> table2[0] [-20,-4.0] >>> table2[0][1] -4.0 Demet (Tuple) Değişkenler Demet değişken, liste değişken türüne çok benzeyen bir türdür. “Sabit” listeler olarak değerlendirilebilirler ve listlerdeki '[ ]' işaretleri yerine '( )' işaretleri ile tanımlanırlar. >>> >>> >>> (2, t = (2, 4, 6, ’temp.pdf’) t = t + (-1.0, -2.0) t 4, 6, ’temp.pdf’, -1.0, 2.0) Bu örnekte t tuple (demet) değişkeni değiştiriliyor gibi görünse de gerçekte olan şudur: t adı verilen bir demet değişkenle (-1.0, 2.0) demet değişkeni toplanmakta (ucuca eklenmekte), bunun sonucunda yeni bir tuple (demet) değişken oluşmaktadır. Bu yeni demet değişkene de t ismi verildiği için t isimli eski değişken yok olmaktadır. Yani t değişmemekte, yeni bir t oluşturulmaktadır! Tıpkı listelerde olduğu gibi! İndeksleme ve dilimleme de aynı listelerde olduğu gibidir. >>> t[1] 4 >>> t[2:] (6, ’temp.pdf’, -1.0, 2.0) >>> 6 in t # 6 t'nin bir elemani midir? True Demet Değişkenler “Değiştirilemezler!” (Immutable) Demet değişkenler, liste değişkenlerde olduğu gibi değişkene eleman ekleyecek (append), çıkaracak (remove), ya da eleman değiştirecek metotlara sahip değildirler. Çünkü liste değişkenler değiştirilebilir (mutable), demet değişkenler değiştirilemezdir (immutable). >>> t = (2, 4, 6, ’temp.pdf’) >>> t.append(0) AttributeError: ’tuple’ object has no attribute 'append’ >>> t.remove(6) AttributeError: ’tuple’ object has no attribute 'remove’ >>> t[1] = -6 TypeError: object does not support item assignment >>> del t[1] TypeError: object doesn’t support item deletion Madem listeler daha yetenekli ve onlarla daha çok şey yapabiliyoruz, neden demet değişkenlere ihtiyaç duyuyoruz? 1. Demet değişkenler içeriklerinin yanlışlıkla silinmesinden bizi korur! 2. Listelere dayalı kodlar demet değişkenlere dayalı kodlardan yavaş çalışır. 3. Karşılaştığınız pek çok kodda demet değişkenler kullanılmıştır. O kodları anlamak ve kullanmak için demet değişkenleri de öğrenmeniz gerekir!