Python ile Nesne Tabanlı Programlama

Nesne Tabanlı Programlama ya da OOP kısaltması olarak da görebileceğiniz Object-Oriented Programming, nesneler üzerine kurulu bir yazılım geliştirme yöntemidir. Klasik tanımı ile gerçek hayatın programlamaya uyarlanması, nesnelerin soyutlanmasıdır. Yazı boyunca kullanacağım obje aynı zamanda nesne demektir.

Gerçek hayattan obje olarak kahve makinesini ele alalım. Bu makinenin özellikleri ve metotları vardır. Makinenin markası, rengi, üzerinde bulunan tuşlar onun özellikleridir (attribute). Açma tuşuna bastığımızda makineyi açması, kahveyi yap tuşuna bastığımızda kahveyi yapması bu objenin fonksiyonu veya metotlarıdır. Şunu belirtmekte fayda var: Metot, sınıf içinde kullanıldığında metot adını alır. Metotlar için objelere ait fonksiyonlar diyebiliriz.

Önceki yazılarda gördüğünüz üzere, örneğin bir liste oluşturmak aslında bir obje oluşturmaktır.

listem = ["Boğaziçi","ODTÜ","Hacettepe"]

Yukarıda listem adında bir obje yarattık.

Bu list veya liste veri tipine ait bir metodu kullanalım. Hangi metotlardı bunlar? Bakalım.

for i in dir(list()):
    if '_' not in i: #burada işimize yaramayacak alt çizgilileri kaldırdık.
        print(i)

append
clear
copy
count
extend
index
insert
pop
remove
reverse
sort

Örneğin, bu listeye append metodunu uygulayarak bir eleman daha ekleyebiliriz.

listem.append("Yıldız Teknik")
listem

['Boğaziçi', 'ODTÜ', 'Hacettepe', 'Yıldız Teknik']

Gelelim sınıf (class) kavramına. Biz obje oluşturmak istediğimizde sınıflardan faydalanacağız. Sınıf dediğimiz kavram özellikler ve metotlardan oluşur. Biz de zaten bu özellik ve metotları kullanarak objeler oluşturabiliyorduk.

class Araba():
    model = "Tesla Model Y"
    renk = "Kırmızı"
    km0_100 = 5.9
    MaksHizKm = 194

Sınıfı oluşturmak için başına class anahtar kelimesini koyduk. Ardından oluşturacağımız sınıfın ismini yazdık. Son olarak da bu arabanın özelliklerini belirttik. Peki, bu sınıfı kullanarak nasıl obje oluşturacağız?

araba1 = Araba()

Objenin ismini belirttikten sonra bunu daha önce oluşturduğumuz sınıfa eşitledik diyebiliriz. Artık bu obje, bu sınıfın özelliklerini kullanacak. Örneğin, bu objenin modeline ve ulaşabileceği maksimum hıza bakmak için obje adının yanına nokta koyuyoruz ve özelliğin ismini yazıyoruz.

araba1.model

'Tesla Model Y'

araba1.MaksHizKm

194

Birden fazla obje yaratılarak onların da özelliklerine bakılabilir fakat her bir objenin özelliği aynı olacaktır. Örnekten ilerlersek, Tesla Model S ve Porsche Taycan’ı da obje olarak oluşturmak istediğimizi varsayalım. Bunun için init metodundan faydalanacağız. init, oluşturulan sınıfın ana yapısıdır ve bir sınıf oluşturulurken otomatik olarak program tarafından yazılır; diğer bir ifade ile default bir şekilde gelir.

class Araba():
    model = "Tesla Model Y"
    renk = "Kırmızı"
    km0_100 = 5.9
    MaksHizKm = 194
    
    def __init__(self):
        print("init metodu çalıştı.")

araba1 = Araba()

init metodu çalıştı.

Bir de içine self adında bir anahtar kelime koyduk. self yardımı ile referans verebileceğiz ya da objelerimizi tanımlayabileceğiz diyebiliriz. Gelin örneğimize devam ederek daha iyi anlayalım.

class Araba():
    
    def __init__(self,model,renk,km0_100,MaksHizKm):
        
        self.model = model
        self.renk = renk
        self.km0_100 = km0_100
        self.MaksHizKm = MaksHizKm

Artık istediğimiz özelliklere sahip modelimizi oluşturabiliriz. Bunu yaparken Python, self’i otomatik olarak gönderdiği için diğer özelliklerini girmek ile başlayacağız.

araba1 = Araba("Tesla Model S","Kırmızı",2.4,259)
araba2 = Araba("Porsche Taycan","Beyaz",2.6,260)

Şimdi tanımladığımız özellikleri alabiliriz.

print("Araba-1\nModel: {}\nRenk: {}\n0-100 (Saniye): {}\nMaks Hız (KM): {}".format(araba1.model,araba1.renk,araba1.km0_100,araba1.MaksHizKm))

Araba-1
Model: Tesla Model S
Renk: Kırmızı
0-100 (Saniye): 2.4
Maks Hız (KM): 259
print("Araba-2\nModel: {}\nRenk: {}\n0-100 (Saniye): {}\nMaks Hız (KM): {}".format(araba2.model,araba2.renk,araba2.km0_100,araba2.MaksHizKm))

Araba-2
Model: Porsche Taycan
Renk: Beyaz
0-100 (Saniye): 2.6
Maks Hız (KM): 260

Objenin özelliklerini oluşturmayı öğrendik. Şimdi objenin metotlarını da tanımlayalım.

class Kitap():
    
    def __init__(self,isim,yazar,kategori,fiyat):
        self.isim = isim
        self.yazar = yazar
        self.kategori = kategori
        self.fiyat = fiyat
        
    def bilgiler(self):
        print("""
        
        Kitap objesinin özellikleri:
        
        İsmi: {}
        Yazarı: {}
        Kategorisi: {}
        Fiyatı: {} TL
        
        """.format(self.isim,self.yazar,self.kategori,self.fiyat))

kitap = Kitap("Körlük","Jose Saramago","Roman (Çeviri)",19.41)

Sınıfın içinde bilgiler adında bir metot oluşturduk. Bu metodu çalıştırdığımızda bize obje ile ilgili bilgiler verecek.

kitap.bilgiler()

        Kitap objesinin özellikleri:
        
        İsmi: Körlük
        Yazarı: Jose Saramago
        Kategorisi: Roman (Çeviri)
        Fiyatı: 19.41 TL

Obje ile ilgili bilgileri veren bilgiler metodunun yanında bir de kitabın fiyatına indirim yapacak bir metot ekleyelim.

class Kitap():
    
    def __init__(self,isim,yazar,kategori,fiyat):
        self.isim = isim
        self.yazar = yazar
        self.kategori = kategori
        self.fiyat = fiyat
        
    def bilgiler(self):
        print("""
        
        Kitap objesinin özellikleri:
        
        İsmi: {}
        Yazarı: {}
        Kategorisi: {}
        Fiyatı: {} TL
        
        """.format(self.isim,self.yazar,self.kategori,self.fiyat))
        
    def indirim(self,miktar):
        self.fiyat -= miktar

kitap = Kitap("Körlük","Jose Saramago","Roman (Çeviri)",19.41)
kitap.indirim(4.41)

Fiyata 4.41 TL’lik bir indirim yaptık. Bilgilerini inceleyebiliriz.

kitap.bilgiler()

        Kitap objesinin özellikleri:
        
        İsmi: Körlük
        Yazarı: Jose Saramago
        Kategorisi: Roman (Çeviri)
        Fiyatı: 15.0 TL

Şimdi gelin bir sınıfın başka bir sınıftan özellikler ve metotlar alabilmesi konusuna bakalım. Buna kalıtım (inheritance) diyeceğiz.

class VeriIscisi():
    
    def __init__(self,departman,deneyim,maas):
        
        self.departman = departman
        self.deneyim = deneyim
        self.maas = maas
        
    def bilgiler(self):
        print("""
        
        Departman: {}
        Deneyim: {} Yıl
        Maaş: {} TL
        
        """.format(self.departman,self.deneyim,self.maas))
        
    def departmanDegistir(self,yeni_departman):
        
        self.departman = yeni_departman

Tıpkı bir önceki örnekte olduğu gibi bir sınıf tanımladık. Bu sınıfın içine özellikleri ve metotları attık. Kalıtım için VeriYoneticisi adında bir class oluşturacağız ve VeriIscisi sınıfının bütün özelliklerini ve metotlarını bu sınıfın içine dahil edeceğiz.

class VeriYoneticisi(VeriIscisi):
    pass

Artık VeriYoneticisi sınıfı, VeriIscisi sınıfının bütün özelliklerini ve metotlarını aldı. Eklediğimiz pass ise ‘şimdilik boş geç hata vermesin, daha sonra dolduracağım’ demektir. Boş bir sınıf oluşturup pass koymazsanız Python’da bu hata anlamına gelir.

Hadi test edelim.

veriyoneticisi1 = VeriYoneticisi("Veri Temizleme",10,10000)

veriyoneticisi1 adında bir obje oluşturduk. Bu objeyi VeriYoneticisi sınıfını kullanarak yaptık ama orada da VeriIscisi sınıfından miras almıştık. Zaten VeriYoneticisi sınıfının içinde de bir şey yapmadık (pass).

veriyoneticisi1.bilgiler()

        Departman: Veri Temizleme
        Deneyim: 10 Yıl
        Maaş: 10000 TL

Gördüğünüz gibi başarılı bir miras olmuş. Burada çalışan init VeriIscisi sınıfına ait init’tir. Gelin bir de diğer bir metot olan departmanDegistir’i kullanalım.

veriyoneticisi1.departmanDegistir("Veri Tedarik")

veriyoneticisi1’i Veri Temizleme departmanından Veri Tedarik departmanına aldık.

veriyoneticisi1.bilgiler()

        Departman: Veri Tedarik
        Deneyim: 10 Yıl
        Maaş: 10000 TL

Daha önce pass ile geçtiğimiz VeriYoneticisi sınıfının içine ayrıca bir metot yazalım.

class VeriYoneticisi(VeriIscisi):
    def zam(self,miktar):
        self.maas += miktar

Şimdi veriyoneticisi2’yi oluşturalım ve zam yapalım.

veriyoneticisi2 = VeriYoneticisi("Algoritma Geliştirme",12,15000)
veriyoneticisi2.zam(1000)
veriyoneticisi2.bilgiler()

        Departman: Algoritma Geliştirme
        Deneyim: 12 Yıl
        Maaş: 16000 TL

Gördüğünüz gibi VeriIscisi sınıfının özelliklerini ve metotlarını aldığımız gibi bir de üstüne VeriYoneticisi sınıfına zam metodunu ekledik ve veriyoneticisi2 objesine zam yaptık.

Eğer miras aldığımız bir sınıfın metodunu aynı isimle yeniden tanımlarsak bu durumda yeniden tanımlama veya geçeriz kılma (override etme/overriding) ile karşılaşacağız. Yani, bu durumda artık sonradan içinde oluşturulan sınıfın metodu kullanılacaktır.

Diyelim ki init metodunu yeniden tanımlamak istiyoruz. İşte bu durumda override etmiş olacağız.

class VeriIscisi():
    
    def __init__(self,departman,deneyim,maas):
        
        self.departman = departman
        self.deneyim = deneyim
        self.maas = maas
        
    def bilgiler(self):
        print("""
        
        Departman: {}
        Deneyim: {} Yıl
        Maaş: {} TL
        
        """.format(self.departman,self.deneyim,self.maas))
        
    def departmanDegistir(self,yeni_departman):
        
        self.departman = yeni_departman


class VeriYoneticisi(VeriIscisi):
    
    def __init__(self,departman,deneyim,maas,sorumluluk): #sorumluluk eklendi.
        
        self.departman = departman
        self.deneyim = deneyim
        self.maas = maas
        self.sorumluluk = sorumluluk
        
    def bilgiler(self):
        print("""
        
        Departman: {}
        Deneyim: {} Yıl
        Maaş: {} TL
        Sorumluluk: {} Kişi
        
        """.format(self.departman,self.deneyim,self.maas,self.sorumluluk))
    
    def zam(self,miktar):
        self.maas += miktar
veriyoneticisi3 = VeriYoneticisi("Veri Görselleştirme",10,13000,3)
veriyoneticisi3.bilgiler()

        Departman: Veri Görselleştirme
        Deneyim: 10 Yıl
        Maaş: 13000 TL
        Sorumluluk: 3 Kişi

self.sorumluluk = sorumluluk hariç VeriYoneticisi sınıfındaki init’te VeriIscisi sınıfının init’ini kullandık (self.departman = departman,self.deneyim = deneyim,self.maas = maas). Biz bunları yazmadan super anahtar kelimesi ile çekebiliriz.

class VeriIscisi():
    
    def __init__(self,departman,deneyim,maas):
        
        self.departman = departman
        self.deneyim = deneyim
        self.maas = maas
        
    def bilgiler(self):
        print("""
        
        Departman: {}
        Deneyim: {} Yıl
        Maaş: {} TL
        
        """.format(self.departman,self.deneyim,self.maas))
        
    def departmanDegistir(self,yeni_departman):
        
        self.departman = yeni_departman


class VeriYoneticisi(VeriIscisi):
    
    def __init__(self,departman,deneyim,maas,sorumluluk):
        
        super().__init__(departman,deneyim,sorumluluk) #buraya dikkat.
        self.sorumluluk = sorumluluk
        
    def bilgiler(self):
        print("""
        
        Departman: {}
        Deneyim: {} Yıl
        Maaş: {} TL
        Sorumluluk: {} Kişi
        
        """.format(self.departman,self.deneyim,self.maas,self.sorumluluk))
    
    def zam(self,miktar):
        self.maas += miktar
veriyoneticisi3 = VeriYoneticisi("Veri Görselleştirme",10,13000,3)
veriyoneticisi3.bilgiler()

        Departman: Veri Görselleştirme
        Deneyim: 10 Yıl
        Maaş: 3 TL
        Sorumluluk: 3 Kişi

Gördüğünüz gibi yine çalıştı.

Artık gelin geniş çaplı bir uygulama yapalım ve tüm öğrendiklerimizi toparlayalım. Uygulamamız kumanda ile ilgili olacak.

Başlamadan önce modül kavramından biraz bahsetmek istiyorum. Modüller içerisinde metotlar, sınıflar ve objeler barındıran yapılardır. Bu modüller kod yazarken bizlere son derece kolaylık sağlıyor ki bunu yapacağımız uygulamalarda sık sık göreceğiz. R kullananlar için oradaki kütüphane mantığı ile aynı diyebiliriz. Bu modülleri Python’ı indirirken hazır elde edebiliyoruz. Ayrıca Github’tan da erişip onlardan faydalanabiliriz.

Peki, bir modül içeriye nasıl aktarılır?

Bir modülü (örnek olarak math) import ile içeriye aktarıp tüm fonksiyonlarından aşağıdaki gibi faydalanabiliriz.

import math

Modülün içinde hangi fonksiyonların olduğunu görmek için şunu yapabiliriz.

dir(math)

#Bazılarını ekledim.

.
.
.
'pi',
'pow',
'prod',
'radians',
'remainder',
'sin',
'sinh',
'sqrt',
'tan',
'tanh',
'tau',
'trunc']

Eğer bu fonksiyonların (örnek olarak sqrt) ne işe yaradığını görmek istersek de şunu yapabiliriz.

help(math.sqrt)

Help on built-in function sqrt in module math:

sqrt(x, /)
    Return the square root of x.

#Tümüne bakmak için help(math) yazılabilir.

Bir fonksiyondan (örnek olarak sqrt) nasıl faydalanabileceğimize bakalım. Bunun için modül ismini yazdıktan sonra nokta koyuyoruz ve fonksiyonun ismini yazıyoruz.

math.sqrt(81)

9.0

Modül import edilirken istenilen bir isimle de bu yapılabilir.

import math as matematik
matematik.sqrt(81)

9.0

Araya bir as koyarak istediğimiz isim ile çağırmış olduk.

Import etmenin bir diğer yolu bütün fonksiyonları dahil etmektir.

from math import *

Sonuna * koyarak tüm fonksiyonları dahil etmek istediğimizi belirttik.

sqrt(81)

9.0

Artık başına modülü koymadan direkt olarak fonksiyondan yararlanmış olduk. Tabi her zaman * koymak zorunda değiliz. Belirlediğimiz fonksiyonları da dahil edebiliriz. Örneğin, sqrt ve sin fonksiyonlarını dahil edelim.

from math import sqrt,sin

Araya virgül koyarak istediğimiz kadar fonksiyon dahil edebiliriz.

Peki, son olarak eğer önce bir fonksiyon tanımlasak ardından da modülün fonksiyonundan faydalansak program hangisini dikkate alır? Deneyelim.

def sqrt(sayi):
    print("Benim fonksiyonum çalışır.")
    return sayi**(1/2)

from math import sqrt

sqrt(81)

9.0

Gördüğünüz gibi eğer bizim oluşturduğumuz fonksiyon çalışsaydı ekrana bir yazı basacaktı. Fakat program modülün fonksiyonunu dikkate aldı. Tam tersi olsaydı? Yani, önce modülün fonksiyonunu dahil etsek ardından da kendi fonksiyonumuzu tanımlasak?

from math import sqrt

def sqrt(sayi):
    print("Benim fonksiyonum çalışır.")
    return sayi**(1/2)

sqrt(81)

Benim fonksiyonum çalışır.
9.0

Gördüğünüz gibi bizim fonksiyon çalıştı.

Modülü anladığımıza göre uygulamamıza geçebiliriz.

Başlamadan önce iki tane modülden faydalanacağız: random ve time. random ile random sayı üreteceğiz ve kanallar arası random geçiş yapacağız; time ile de programa gerçeklik havası katmak için bazı işlemleri bir süre beklemeye alacağız.

import random, time

Yazının sonunda toplu olarak vereceğim kodları önce parça parça inceleyelim. Sizler de isterseniz bu kod parçalarını bir bütün olacak şekilde yazmaya başlayın. Yukarıdaki modülleri de eklemeyi unutmayın.

Sınıfı oluşturuyoruz.

class Kumanda():

init metodunu tanımlıyoruz.

def __init__(self,durum = "Kapalı", ses = 0, liste = ["National Geographic"], kanal = "National Geographic"):
        
        self.durum = durum
        self.ses = ses
        self.liste = liste
        self.kanal = kanal

TV açıksa kapatacak; kapalı ise açacak metodu yazıyoruz.

def durumDegistir(self):
        
        if self.durum == "Kapalı":
            self.durum = "Açık"
            print("TV Açılıyor...")
            time.sleep(1)
            print("TV Açıldı.")
        else:
            self.durum = "Kapalı"
            print("TV Kapatılıyor...")
            time.sleep(1)
            print("TV Kapatıldı.")

TV’nin sesini artıracak veya azaltacak metodu yazıyoruz.

def sesAyar(self):
        
        while True:
            
            ses_girdi = input("Ses yönü:\nArtır: +\nAzalt: -\nÇıkış: q")
            
            if ses_girdi == "+":
                if self.ses != 30:
                    self.ses += 1
                    print("Ses: ",self.ses)
            elif ses_girdi == "-":
                if self.ses != 0:
                    self.ses -= 1
                    print("Ses: ",self.ses)
            else:
                break

TV’ye yeni kanal ekleyecek metodu ekliyoruz.

def kanalEkle(self,yeni_kanal):
        
        self.liste.append(yeni_kanal)
        time.sleep(1)
        print("Kanal eklendi.")

TV’de kanallar arası random dolaşmamızı sağlayacak metodu ekliyoruz.

def randomKanal(self):
        
        hangi_kanal = random.randint(0,len(self.liste)-1)
        
        self.kanal = self.liste[hangi_kanal]
        print("Kanal: ",self.kanal)

Sıradaki son iki metoda dikkat: len ve str. Bunlar özel metotlardan ikisidir. Bu metotları biz özel olarak çağırmıyoruz ama her sınıfta bulunuyorlar. Mesela yazının başlarında gördüğümüz bu özel metotlardan init, biz tanımlamasak da program tarafından tanımlanıyordu. Biz bunu özelleştiriyorduk ve aslında kendi init metodumuzu yazmış oluyorduk. Sıradaki metotlar len ve str’da da aynısını yapmış olacağız.

Uzunluk diyebileceğimiz len ile kanal sayısı bilgisi verecek metodu yazıyoruz.

def __len__(self):
        
        return len(self.liste)

str ile TV bilgilerini verecek metodu yazıyoruz.

def __str__(self):
        
        return "Durum: {}\nSes: {}\nListe: {}\nKanal: {}".format(self.durum, self.ses, self.liste, self.kanal)

Şimdi bir kumanda adında obje yaratalım.

kumanda = Kumanda()

Kullanıcıya hangi işlemin ne işe yarayacağı ile ilgili bilgi verelim.

print("""

İşlem-1: TV açık ise kapat; kapalı ise aç.

İşlem-2: TV sesini artır ya da azalt.

İşlem-3: Yeni kanal ekle. Virgül ile ayırın.

İşlem-4: Kanal sayısını öğren.

İşlem-5: Random kanal aç.

İşlem-6: Bilgileri öğren.

İşlem-q: Programdan çık.

""")

Ve işlemleri gerçekleştirmek için kodlarımızı yazalım.

while True:
    
    islem = input("İşlem: ")
    
    if islem == "q":
        break
        
    elif islem == "1":
        kumanda.durumDegistir()
    
    elif islem == "2":
        kumanda.sesAyar()
        
    elif islem == "3":
        girilecek_kanallar = input("Kanallar: ")
        alinan_liste = girilecek_kanallar.split(",")
        
        for ekle in alinan_liste:
            kumanda.kanalEkle(ekle)
            
    elif islem == "4":
        print("Kanal Sayısı:",len(kumanda))
        
    elif islem == "5":
        kumanda.randomKanal()
        
    elif islem == "6":
        print(kumanda)
        
    else:
        print("Geçersiz işlem!")

İşte bu kadar.

Kodların tamamına aşağıdan ulaşabilirsiniz.

import random, time

class Kumanda():
    
    def __init__(self,durum = "Kapalı", ses = 0, liste = ["National Geographic"], kanal = "National Geographic"):
        
        self.durum = durum
        self.ses = ses
        self.liste = liste
        self.kanal = kanal
        
    def durumDegistir(self):
        
        if self.durum == "Kapalı":
            self.durum = "Açık"
            print("TV Açılıyor...")
            time.sleep(1)
            print("TV Açıldı.")
        else:
            self.durum = "Kapalı"
            print("TV Kapatılıyor...")
            time.sleep(1)
            print("TV Kapatıldı.")
            
    def sesAyar(self):
        
        while True:
            
            ses_girdi = input("Ses yönü:\nArtır: +\nAzalt: -\nÇıkış: q")
            
            if ses_girdi == "+":
                if self.ses != 30:
                    self.ses += 1
                    print("Ses: ",self.ses)
            elif ses_girdi == "-":
                if self.ses != 0:
                    self.ses -= 1
                    print("Ses: ",self.ses)
            else:
                break
                
    def kanalEkle(self,yeni_kanal):
        
        self.liste.append(yeni_kanal)
        time.sleep(1)
        print("Kanal eklendi.")
        
    def randomKanal(self):
        
        hangi_kanal = random.randint(0,len(self.liste)-1)
        
        self.kanal = self.liste[hangi_kanal]
        print("Kanal: ",self.kanal)
        
    def __len__(self):
        
        return len(self.liste)
    
    def __str__(self):
        
        return "Durum: {}\nSes: {}\nListe: {}\nKanal: {}".format(self.durum, self.ses, self.liste, self.kanal)
    
    
kumanda = Kumanda()

print("""

İşlem-1: TV açık ise kapat; kapalı ise aç.

İşlem-2: TV sesini artır ya da azalt.

İşlem-3: Yeni kanal ekle. Virgül ile ayırın.

İşlem-4: Kanal sayısını öğren.

İşlem-5: Random kanal aç.

İşlem-6: Bilgileri öğren.

İşlem-q: Programdan çık.

""")

while True:
    
    islem = input("İşlem: ")
    
    if islem == "q":
        break
        
    elif islem == "1":
        kumanda.durumDegistir()
    
    elif islem == "2":
        kumanda.sesAyar()
        
    elif islem == "3":
        girilecek_kanallar = input("Kanallar: ") #girilecek kanalları al.
        alinan_liste = girilecek_kanallar.split(",") #girilen kanalları al. Virgül ile girilen kanalları ayır.
        
        for ekle in alinan_liste: #for döngüsü ile her bir kanalı ekle.
            kumanda.kanalEkle(ekle)
            
    elif islem == "4":
        print("Kanal Sayısı:",len(kumanda))
        
    elif islem == "5":
        kumanda.randomKanal()
        
    elif islem == "6":
        print(kumanda)
        
    else:
        print("Geçersiz işlem!")

OOP ile ilgili daha fazla uygulama yapmayı düşünüyorum. Çünkü OOP, ilk başta anlaşılması zor bir konu olabilir fakat tekrar ettikçe ve bol bol uygulama yaptıkça anlaşılabilecek bir konuya dönüşüyor.

Bu konuyu anlatırken kodları Jupyter Notebook’ta yazdım fakat gelecek uygulamalarda PyCharm ortamına alışmamız için (alışmalıyız diye düşünüyorum) orada yazacağız.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir