Python'da Veri Yapıları ve OOP İlişkileri

Python'da Veri Yapıları ve OOP İlişkileri

Python programlama dili ile veri yapıları ve OOP ilişkilerini öğrenmek isteyenler için detaylı bir rehber Algoritma ve veri tipleri hakkında bilgi sahibi olun, nesne yönelimli programlama teknikleri ile kodlama pratikleri edinin Python veri yapıları ve OOP ile ilgili her şey burada!

Python'da Veri Yapıları ve OOP İlişkileri

Python, son yılların en popüler programlama dilleri arasında yer almaktadır. Bu dil, özellikle veri yapıları ve OOP ilişkileri konusunda oldukça güçlüdür. Bu makalede, Python'da bulunan farklı veri yapıları ve OOP ilişkileri konularında bilgi sahibi olacaksınız.


Listeler

Python'da listeler, farklı veri tiplerini tek bir yapıda tutmamıza izin verir. Liste tipi verilerin tanımlanmasında köşeli parantez kullanılır ve elemanlar virgülle ayrılır. Listeler, değiştirilebilir bir veri yapısına sahip olduğundan, elemanları eklemek ve silmek mümkündür.

Liste elemanlarının indeksleri, 0'dan başlar ve eleman ekleme ve silme işlemleri indekslere göre yapılır. Erol ve Ayşe isimleri için bir liste oluşturmak isteyelim. Bu durumda, aşağıdaki kodu kullanabiliriz:

    isimler = ["Erol", "Ayşe"]

Böylece, "isimler" listesi oluşturulmuş oldu. Listenin içerisindeki elemanlara erişmek için indeks numaraları kullanılır. Örneğin, "isimler" listesindeki ilk elemana, yani "Erol" isimine erişmek istiyorsak kodumuz şöyle olacaktır:

    isimler[0]

Listenin sonuna eleman eklemek istediğimizde ise "append()" fonksiyonunu kullanabiliriz. Örneğin, "isimler" listesine "Can" ismini eklemek istediğimizde, şu şekilde bir kod yazabiliriz:

    isimler.append("Can")

Bu şekilde, "Can" ismi "isimler" listesinin son elemanı olacaktır. Listeler, Python'da oldukça yaygın olarak kullanılan veri yapılarından biridir ve pek çok farklı işlemde kullanışlıdır.


Sözlükler

Python'da kullanılabilecek veri yapılarından biri de sözlüklerdir. Sözlükler, anahtar-değer çiftlerinden oluşur. Anahtar-değer çiftleri, birbirinden farklı isimleriyle sözlüğe eklenir ve bu isimlerle değerlere ulaşılabilir. Sözlük oluşturmak için süslü parantezler ({}) kullanılır.

Bir sözlüğü oluştururken anahtar-değer çiftleri arasına virgül koyulur. Örneğin, {'elma': 2, 'armut': 5, 'muz': 1} şeklinde bir sözlük oluşturulabilir. Bu sözlüğe 'elma', 'armut' ve 'muz' anahtarları verilmiş ve sırasıyla 2, 5 ve 1 değerleri atanmıştır.

Sözlük içindeki her bir değer, anahtarı kullanarak çağrılabilir. Örneğin, yukarıdaki sözlükte 'elma' anahtarına karşılık gelen değer 2'dir. Bu değere, sözlük['elma'] şeklinde ulaşılabilir. Eğer sözlükte olmayan bir anahtar kullanılırsa, hata verir.

Python'da iç içe sözlükler oluşturulabilir ve bu sayede daha karmaşık veri yapıları oluşturmak mümkün hale gelir. Ayrıca, sözlüklerin diğer veri yapıları ile birlikte kullanılması da sıkça kullanılır.

Anahtar Değer
'elma' 2
'armut' 5
'muz' 1

Sözlükler, programlama dillerinde sıkça kullanılan veri yapılarından biridir ve Python'da da oldukça kullanışlıdır. Anahtar-değer çiftleri sayesinde, verilere hızlı ve kolay erişim sağlanabilir. Sözlükleri kullanarak, örneğin bir kitaplık uygulaması gibi ilgili bilgilerin saklanması gerektiği durumlarda oldukça etkili bir çözüm sunulabilir.


Setler

Python'da set veri yapısı, benzersiz elemanlara sahip bir coleksiyon olarak kullanılabilir. Bu elemanlar, her tür veri tipini içerebilir ve tekrarlanmazlar. Set veri yapısı, matematik ve mantıksal işlemleri yapmak için kullanışlıdır.

Örneğin, bir set içinde iki listeyi birleştirmek, kesişimlerini veya farklılıklarını bulmak için kullanılabilir. Ayrıca, verileri sıralamak veya düzenlemek için kullanılmaz. İşlemler diğer koleksiyonlarla benzer şekilde gerçekleştirilebilir.

Aşağıdaki tablo, set veri yapısının yöntemlerini ve açıklamalarını gösterir:

Metod Açıklama
add() Bir eleman ekler
clear() Tüm elemanları siler
copy() Bir setin kopyasını oluşturur
difference() Diğer setler için farklı elemanlar döndürür
intersection() Diğer setler ile kesişen elemanları döndürür
isdisjoint() Diğer setler ile kesişen eleman varsa "false" döndürür
issubset() Diğer bir setin alt kümesi ise "true" döndürür
issuperset() Diğer bir setin üst kümesi ise "true" döndürür
pop() Bir elemanı kaldırır ve döndürür
remove() Bir elemanı kaldırır
symmetric_difference() Diğer setlerde bulunmayan elemanlardan bir set oluşturur
union() Diğer setlerin elemanları ile birlikte bir set oluşturur
update() Diğer setlerde bulunan elemanları ekler

Set veri yapısı, birden fazla elemanın tek bir koleksiyonda saklanması gerektiği, benzersiz eleman gerektiren ve birleştirme, kesişim, farklılık gibi işlemlerin yapılması gereken durumlarda kullanılabilir.


Frozensetler

Frozenset, Python'daki veri yapılarından biridir. Set veri yapısına benzer, ancak temel fark, frozensetlerin değiştirilemez olmasıdır. Yani bir kez oluşturulduktan sonra, frozenset elemanları artık değiştirilemez. Bu nedenle, frozensetler, sabit bir veri yapısı için uygun olan durumlarda kullanılır.

Frozensetlerin kullanımı oldukça basittir. Öncelikle, frozenset oluşturmak için set() fonksiyonu kullanılır. Daha sonra, frozenset elemanları belirlenir ve frozenset() fonksiyonu çağrılarak frozenset veri yapısı oluşturulur.

Bir frozenset örneği için aşağıdaki kod kullanılabilir:

    frozen_set = frozenset([1, 2, 3, 4])

Bu örnekte frozenset, [1, 2, 3, 4] elemanlarının dondurularak oluşturulduğu bir frozenset veri yapısına dönüştürümüdür.

Frozenset veri yapısı, bazı metodlarla birlikte gelir. Bu metodlar, frozenset veri yapısının işlevselliğini artırmaya yardımcı olur. Bu metodlar şunlardır:

  • copy(): Frozenset veri yapısının kopyasını oluşturmak için kullanılır.
  • difference(): Bir frozenset ile diğer bir frozenset arasındaki farkları bulmak için kullanılır.
  • intersection(): İki frozensetin kesişim elemanlarını bulmak için kullanılır.
  • issubset(): Bir frozensetin diğer bir frozensetin alt kümesi olup olmadığını kontrol etmek için kullanılır.

Frozenset veri yapısı, Python'da sürekli olarak değişen yapıları sabitlemek için kullanışlı bir araçtır. Bu nedenle, frozensetler, verilerin belli bir noktada sabit kalmasını isteyen uygulamalar için ideal bir çözümdür.


DictViews

Python'daki dictview veri yapısı, sözlüklerdeki anahtar ve değer çiftleri üzerinde işlem yapmak için kullanılır. Bu veri yapısı, sözlüklerin anahtarları veya değerleri üzerinde filtreleme, sıralama ve işlem yapma gibi işlemler için kullanılabilir.

Dictview'ler, sözlükler ile benzer özelliklere sahiptir ve onlar gibi anahtar-değer çiftlerini içerir. Ancak dictview'ler, sözlüklerin bir görüntüsü veya görünümü olarak düşünülebilir. Yani, sözlükteki anahtar-değer çiftlerinin bir görünümünü sunar, ancak gerçek sözlük yapısını değiştirmez. Bu nedenle, sözlüğün değiştirilmesi, dictview üzerinde herhangi bir etkiye sahip olmaz.

Dictview veri yapısı, sözlük veri yapısının sağladığı esnekliğe ek olarak, anahtar-değer çiftleri üzerinde daha fazla işlem yapma imkanı verir. Dictview'lerin bir diğer avantajı ise, bellek kullanımının düşük olmasıdır.

Dictview veri yapısının örnek olarak bir sözlük tarafından kullanıldığını varsayalım:

Örnek Sözlük
{'Kitap': 10, 'Kalem': 5, 'Defter': 3}

Bu sözlük, örneğin bir mağazanın stok bilgileri üzerinde çalışırken dictview veri yapısı kullanılarak şu işlemler yapılabilir:

  • Sadece stokta kalan ürünleri görüntülemek için, stoğu sıfıra eşit olmayan öğeleri içeren bir dictview oluşturulabilir.
  • Stokta bulunan ürünleri alfabetik olarak sıralamak için, anahtarları alfabetik sıraya göre sıralamak üzere bir dictview oluşturulabilir.
  • Satılan ürünleri stoğumuzdan çıkarmak için, stoktaki bir ürünün değerini, örneğin kalem için 1 azaltmak için bir dictview oluşturulabilir.

Bu örnekler, dictview veri yapısının sözlükler üzerindeki esnekliği ve işlemleri nasıl kolaylaştırdığını göstermektedir.


Tuplelar

Tuple, diğer bir Python veri yapısıdır ve liste veri yapısına benzerdir. Fakat, tuple listelerinin aksine, tuplelar değiştirilemez. Tuplelar, normal parantezler içinde tanımlanır ve elemanları virgülle ayrılır. Veri yapısındaki elemana tek bir indeksle ulaşılabilir. Tuplelar listelerden daha hızlı olduğu için okuma işlemi ile ilgili olmayan programların performansını arttırmak için kullanılabilirler.

Tuplelar, birden fazla değer için aynı zamanda kullanışlıdır. Örneğin, tuple veri yapısı, bir öğrencinin adı, sınıfı ve aldığı notlar gibi farklı değişkenlerin olduğu bir senaryoda kullanılabilir. Bu farklı veriler, tuple içerisinde sırayla yazılabilir ve çağrılabilir. Tuple, listenin aksine özelleştirilemez olduğundan, bu verilerin emniyetliği korunur.

Tuplelar, dilimleme ve dilimleme işlemleri gerektirdiğinde kullanılabilir. İleride değiştirmeyi planlamadığınız ve sabit bir değer olan daha küçük veri kümeleri ile çalışmak için yapılandırmak iyi bir uygulamadır. Ayrıca, özellikle diziler, listeler ve sözlüklerle çalışmaya start verirken tuplelar kullanmak daha kolaydır.

Bir diğer kullanım alanı ise, daha büyük projelerde takım çalışması yapılırken tuple yapısı ile beraber oluşturulan değişkenler ortak bir dil ile anlaşılabilir ve bir arada tutulabilir. Tuple, yazılım geliştirme sürecinde kodların okunabilirliğini artırabilir ve kod üretim hızını da yükseltebilir.

Sonuç olarak, tuple yapısı değiştirilemez, performanslı ve okunabilirliği artıran bir Python veri yapısıdır. Özellikle işlem gerektirmeyen ve sabit değerlerin kullanıldığı durumlarda kullanmak uygun olabilir. Değişkenlerin, koleksiyonların ve farklı veri tiplerinin saklanması için tuple yapısını değerlendirebilirsiniz.


OOP İlişkileri

OOP (Object-Oriented Programming) programlama dilinde, nesneler arası ilişkiler bir sınıftan başka bir sınıfa nasıl aktarılacağı üzerinde yoğunlaşmaktadır. Python'da da OOP ilişkileri oluşturmak için üç temel yolla kullanılabilir:

  • İçerme: Bu, bir sınıfın başka bir sınıf içinde nasıl kullanılacağıdır. Bazı durumlarda, bir sınıf bir başka sınıfın özelliklerini veya davranışlarını içermesi gerekebilir. Bu durumda, bir sınıfın öğesi olarak başka bir sınıf sınıflandırılabilir. Bu ilişki, bir "yardımcı sınıf" olarak adlandırılır. Yardımcı sınıf, ana sınıfta kullanılabilen özellikleri ve davranışları sağlar.
  • Miras: Bu, alt sınıfların üst sınıflardan özellikleri ve davranışları nasıl miras alabileceği hakkındadır. Miras, kodun yeniden kullanımını kolaylaştırır, daha az kod kullanarak daha fazla işlevsellik sağlar ve kodun sürdürülebilirliğini artırır. Python'da miras kullanmak, bir alt sınıfın, bir üst sınıftan aldığı özelliklerin yanı sıra kendine özgü özellikleri ve davranışları da içerebileceği anlamına gelir.
  • Kompozisyon: Bu, bir sınıfın başka bir sınıfta nasıl kullanılabileceği ile ilgilidir. İki sınıf arasındaki kompozisyon ilişkisi, bir sınıfta diğer bir sınıfınızı tutan veya içeren nesneleri belirtir. Bu ilişki, "kompozisyon" olarak adlandırılır. Bu ilişki sayesinde, bir sınıf kendi işlevselliğini başka bir sınıftan bağımsız bir şekilde yönetebilir.

Python programlama dili, OOP programlama dilinin en popüler dillerinden biridir. Bu nedenle, Python özellikle bu OOP ilişkileri için uygun bir dil olarak öne çıkmaktadır. Programlama dilinde, birçok özellik ve işlevsellik sunan bu ilişkiler, kodun yeniden kullanımını ve bakımını kolaylaştırarak kodun sürdürülebilirliğini sağlar. Python'da OOP ilişkileri ile çalışmak, güçlü, anlamlı ve kolay okunabilir kodlar oluşturmak için son derece faydalıdır.


İçerme

İçerme (Composition) Nedir?

İçerme (composition), Python'da bir sınıfın başka bir sınıfın içinde kullanılmasıdır. Bu ilişki, sınıfın bir kısmının veya tümünün başka bir sınıf tarafından kontrol edilmesine olanak tanır. İçerme genellikle "HAS-A" ilişkisi olarak adlandırılır, çünkü bir sınıf, diğer sınıfın bir öğesini içerir.

Örneklerle İçerme İlişkisi

Bir örnek ile açıklamak gerekirse; bir araba sınıfını ele alalım. Bu sınıfta, motor, tekerlek ve direksiyon öğeleri bulunur. Ancak bir araba sınıfı, kendisine has bir motor sınıfını kullanabilir. Bu nedenle, Araba sınıfı, Motor sınıfına sahip olur. Bu ilişki, araba sınıfına bir motor eklemek veya çıkarmak için daha fazla esneklik sağlar. Eklemek istediğiniz özellikleri motor sınıfında ekleyerek arabalar arasında paylaşabilirsiniz. Böylece Motor sınıfı, Araba sınıfının bir öğesi olur ve Araba sınıfı, Motor sınıfının bir örneğini "tutar" (holds) veya içerir.

Bir örnek daha vermek gerekirse; bir ev sınıfını ele alalım. Bu sınıfta, odalar, mobilyalar, eşyalar ve kapılar bulunur. Ancak bu evin bir bahçesi de olabilir. Bahçe sınıfını yazdıktan sonra, Ev sınıfına bir bahçe objesi ekleyebiliriz. Böylece bir sınıf, diğer sınıfın bir öğesini "sahip" ya da "tutar".

İçerme ilişkisi, programcılara daha modüler ve yeniden kullanılabilir kod oluşturma imkanı sağlar. Böylece kod düzenli hale gelir ve kolayca yönetilebilir hale gelir.


Miras

Miras, object-oriented programming (OOP) ile ilgilidir ve bir sınıfın başka bir sınıfın özelliklerini ve davranışlarını alması anlamına gelir. Bu, kod tekrarını azaltır ve programlama sürecini daha hızlı hale getirir.

Bir alt sınıf, bir üst sınıfın tüm özelliklerini ve davranışlarını miras alabilir. Alt sınıf, üst sınıfın özelliklerinin yanı sıra kendi özelliklerini ve davranışlarını da barındırabilir. Bu, kalıtım ağaçları oluşturarak, karmaşık programlarda kod tekrarını azaltmaya yardımcı olur.

Miras almak için, alt sınıfın üst sınıfı belirtmesi gerekir. Örneğin:

class UstSinif:
    # üst sınıf özellikleri ve davranışları
class AltSinif(UstSinif):
    # alt sınıf özellikleri ve davranışları     # üst sınıfın özelliklerini ve davranışlarını otomatik olarak miras alır

Yukarıdaki örnek, alt sınıfın, üst sınıfın özelliklerini ve davranışlarını otomatik olarak miras aldığını gösterir. Böylece, alt sınıf, üst sınıfta tanımlanan tüm özellikleri ve davranışları kullanabilir.

Bir sınıfın özellikleri ve davranışları değiştirilerek veya genişletilerek miras alınabilir. Bu, alt sınıfın üst sınıfın özelliklerini ve davranışlarını daha özelleştirilmiş bir şekilde kullanmasına olanak tanır. Örneğin:

class UstSinif:
    def __init__(self):         self.ornek = "Üst Sınıf Örneği"
    def bir_fonksiyon(self):         print("Üst Sınıf Fonksiyonu Çağırıldı")
class AltSinif(UstSinif):
    def __init__(self):         super().__init__()
    def bir_fonksiyon(self):         print("Alt Sınıf Fonksiyonu Çağırıldı")

Bu örnekte, alt sınıfın __init__() ve bir_fonksiyon() metodları özelleştirilmiştir. Ancak, alt sınıfın ilk önce üst sınıfın __init__() metodunu çağırması için super().__init__() kullanmıştır. Böylece, alt sınıfın özellikleri, üst sınıfın özellikleriyle birlikte kullanılır.

Miras, Python'da OOP programlama sürecini kolaylaştıran önemli bir özelliktir. Kalıtım ağaçları oluşturarak kod tekrarını azaltmak ve programlama sürecini hızlandırmak mümkündür.


Kompozisyon

Kompozisyon, bir sınıfın başka bir sınıfta nasıl kullanılabileceğini belirten bir OOP ilişki türüdür. Bu yapı, sınıfların birbirleri içinde kullanılmasını ve birbirleriyle etkileşimini sağlar. Kompozisyonu anlamak için iki sınıf örneği verilebilir: Araba ve Motor. Araba sınıfı, bir motoru kullanabilecek ve onu başlatıp durdurabilecek bir sınıftır. Bu nedenle, Araba sınıfı Motor sınıfını içeren bir yapıya sahip olabilir.

Bir başka örnek, bir Tüketici sınıfıdır. Bu sınıf, fatura ödeme işlemlerini gerçekleştirmek için Banka sınıfını kullanabilir. Bu durumda, Tüketici sınıfı, Banka sınıfını kullanarak fatura ödemeleri yapabilir. Bu yapı, bir sınıfın başka bir sınıfın özelliklerini ve işlevlerini kullanmasına olanak tanır ve sınıflar arasındaki kod tekrarını azaltır.

Tablo olarak ifade edildiğinde, kompozisyon şu şekilde anlatılabilir:

Sınıf A Kompozisyon Sınıf B
Araba içerir Motor
Tüketici içerir Banka

Kompozisyon, OOP'nin güçlü bir yönüdür ve kod yeniden kullanımı ile ilgili problemleri çözmeye yardımcı olur. Bu tür bir ilişki, sınıfların birden fazla özelliği ve işlevi kullanmasına olanak tanır ve koddaki tekrarları azaltır. Ancak, doğru bir şekilde kullanılmadığında, kodun karmaşık hale gelmesine neden olabilir ve sınıflar arasındaki bağımlılığı artırabilir. Bu nedenle, kompozisyon kullanırken, iyi tasarlanmış bir kod yapısı ve sınıf hiyerarşisi oluşturmak önemlidir.