Kümeler

Bu bölümde, bir dizi halinde incelediğimiz veri tiplerinin sonuncusu olan kümeleri inceleyeceğiz. Bu bölümün sonunda küme denen şeyin ne olduğunu ve ne işe yaradığını öğrenecekseniz.

İngilizce’de kümeye “set” diyorlar. Python’da nispeten yeni sayılabilecek bir araç olan kümeler hem çok hızlıdır, hem de epey işe yarar.

Kümeleri öğrendiğimizde, bunların kimi zaman hiç tahmin bile edemeyeceğimiz yerlerde işimize yaradığını göreceğiz. Normalde uzun uzun kod yazmayı gerektiren durumlarda kümeleri kullanmak, bir-iki satırla işlerimizi halletmemizi sağlayabilir.

Kümeler, matematikten bildiğimiz “küme” kavramının sahip olduğu bütün özellikleri taşır. Yani kesişim, birleşim ve fark gibi özellikler Python’daki setler için de geçerlidir.

Küme Oluşturmak

Kümelerin bize sunduklarından faydalanabilmek için elbette öncelikle bir küme oluşturmamız gerekiyor. Küme oluşturmak çok kolay bir işlemdir. Örneğin boş bir kümeyi şöyle oluşturuyoruz:

>>> bos_kume = set()

Listeler, demetler ve sözlüklerin aksine kümelerin ayırt edici bir işareti yoktur. Küme oluşturmak için set() fonksiyonundan yararlanıyoruz.

Yukarıda boş bir küme oluşturduk. İçinde öğe de barındıran kümeleri ise şu şekilde oluşturuyoruz:

>>> kume = set(["elma", "armut", "kebap"])

Böylelikle, içinde öğe barındıran ilk kümemizi başarıyla oluşturduk. Dikkat ederseniz, küme oluştururken listelerden faydalandık. Gördüğünüz gibi set() fonksiyonu içindeki öğeler bir liste içinde yer alıyor. Dolayısıyla yukarıdaki tanımlamayı şöyle de yapabiliriz:

>>> liste = ["elma", "armut", "kebap"]

>>> kume = set(liste)

Bu daha temiz bir görüntü oldu. Elbette küme tanımlamak için mutlaka liste kullanmak zorunda değiliz. İstersek demetleri de küme haline getirebiliriz:

>>> demet = ("elma", "armut", "kebap")

>>> kume = set(demet)

Hatta ve hatta karakter dizilerinden dahi küme yapabiliriz:

>>> kardiz = "Python Programlama Dili için Türkçe Kaynak"

>>> kume = set(kardiz)

Kullandığımız karakter dizisinin böyle uzun olmasına da gerek yok. Tek karakterlik dizilerden bile küme oluşturabiliriz:

>>> kardiz = "a"

>>> kume = set(kardiz)

Ama sayılardan küme oluşturamayız:

>>> n = 10

>>> kume = set(n)

TypeError: 'int' object is not iterable

Peki sözlükleri kullanarak küme oluşturabilir miyiz? Evet, neden olmasın?

>>> bilgi = {"işletim sistemi": "GNU", "sistem çekirdeği": "Linux",
... "dağıtım": "Ubuntu GNU/Linux"}

>>> kume = set(bilgi)

Böylece kümeleri nasıl oluşturacağımızı öğrendik. Eğer oluşturduğunuz kümeyi ekrana yazdırmak isterseniz, ne yapacağınızı biliyorsunuz. Burada tanımladığınız küme değişkenini kullanmanız yeterli olacaktır:

>>> kume

{'işletim sistemi', 'sistem çekirdeği', 'dağıtım'}

Bir de şuna bakalım:

>>> kardiz = "Python Programlama Dili"

>>> kume = set(kardiz)

>>> print kume

set(['a', ' ', 'D', 'g', 'i', 'h', 'm', 'l', 'o', 'n', 'P', 'r', 't', 'y'])

Burada bir şey dikkatinizi çekmiş olmalı. Bir karakter dizisini küme olarak tanımlayıp ekrana yazdırdığımızda elde ettiğimiz çıktı, o karakter dizisi içindeki her bir karakteri tek bir kez içeriyor. Yani mesela “Python Programlama Dili” içinde iki adet “P” karakteri var, ama çıktıda bu iki “P” karakterinin yalnızca biri görünüyor. Buradan anlıyoruz ki, kümeler aynı öğeyi birden fazla tekrar etmez. Bu çok önemli bir özelliktir ve pek çok yerde işimize yarar. Aynı durum karakter dizisi dışında kalan öteki veri tipleri için de geçerlidir. Yani mesela eğer bir listeyi küme haline getiriyorsak, o listedeki öğeler küme içinde yalnızca bir kez geçecektir. Listede aynı öğeden iki-üç tane bulunsa bile, kümemiz bu öğeleri teke indirecektir.

>>> liste = ["elma", "armut", "elma", "kebap", "şeker", "armut",
... "çilek", "ağaç", "şeker", "kebap", "şeker"]

>>> for i in set(liste):
...     print i
...
ağaç
elma
şeker
kebap
çilek
armut

Gördüğünüz gibi, liste içinde birden fazla bulunan öğeler, Python’daki kümeler yardımıyla teke indirilebiliyor.

Öğrendiğimiz bu bilgi sayesinde, daha önce gördüğümüz count() metodunu da kullanarak, şöyle bir kod yazabiliriz:

>>> liste = ["elma", "armut", "elma", "kiraz",
... "çilek", "kiraz", "elma", "kebap"]


>>> for i in set(liste):
...     print "%s listede %s kez geçiyor!"%(i, liste.count(i))

elma listede 3 kez geçiyor!
kiraz listede 2 kez geçiyor!
armut listede 1 kez geçiyor!
kebap listede 1 kez geçiyor!
çilek listede 1 kez geçiyor!

Burada set(liste) ifadesini kullanarak, liste öğelerini eşşiz ve benzersiz bir hale getirdik.

Esasında tek bir küme pek bir işe yaramaz. Kümeler ancak birden fazla olduğunda bunlarla yararlı işler yapabiliriz. Çünkü kümelerin en önemli özelliği, başka kümelerle karşılaştırılabilme kabiliyetidir. Yani mesela kümelerin kesişimini, birleşimini veya farkını bulabilmek için öncelikle elimizde birden fazla küme olması gerekiyor. İşte biz de şimdi bu tür işlemleri nasıl yapacağımızı öğreneceğiz. O halde hiç vakit kaybetmeden yolumuza devam edelim.

Kümelerin Metotları

Daha önceki veri tiplerinde olduğu gibi, kümelerin de metotları vardır. Artık biz bir veri tipinin metotlarını nasıl listeleyeceğimizi çok iyi biliyoruz. Nasıl liste için list(); demet için tuple(); sözlük için de dict() fonksiyonlarını kullanıyorsak, kümeler için de set() adlı fonksiyondan yararlanacağız:

>>> dir(set)

['__and__', '__class__', '__contains__', '__delattr__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__iand__', '__init__', '__ior__', '__isub__', '__iter__',
'__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__',
'__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__',
'__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__',
'__str__', '__sub__', '__subclasshook__', '__xor__', 'add',
'clear','copy', 'difference', 'difference_update', 'discard',
'intersection', 'intersection_update', 'isdisjoint', 'issubset',
'issuperset', 'pop', 'remove', 'symmetric_difference',
'symmetric_difference_update', 'union', 'update']

Hemen işimize yarayacak metotları alalım:

>>> for i in dir(set):
...     if "__" not in i:
...         print i
...
add
clear
copy
difference
difference_update
discard
intersection
intersection_update
isdisjoint
issubset
issuperset
pop
remove
symmetric_difference
symmetric_difference_update
union
update

Gördüğünüz gibi kümelerin epey metodu var. Bu arada if "__" not in i satırında “_” yerine “__” kullandığımıza dikkat edin. Neden? Çünkü eğer sadece “_” kullanırsak symmetric_difference ve symmetric_difference_update metotları çıktımızda yer almayacaktır.

Unutmadan söyleyelim: Kümeler de, tıpkı listeler ve sözlükler gibi, değiştirilebilir bir veri tipidir.

clear metodu

Kümelerle ilgili olarak inceleyeceğimiz ilk metot clear(). Bu metodu daha önce sözlükleri çalışırken de görmüştük. Sözlüklerde bu metodun görevi sözlüğün içini boşaltmak idi. Burada da aynı vazifeyi görür:

>>> km = set("adana")

>>> for i in km:
...     print i
...
a
d
n

>>> km.clear()

>>> km
set([])

Burada önce “km” adlı bir küme oluşturduk. Daha sonra da clear() metodunu kullanarak bu kümenin bütün öğelerini sildik. Artık elimizde boş bir sözlük var.

copy metodu

Listeler ve sözlükleri incelerken copy() adlı bir metot öğrenmiştik. Bu metot aynı zamanda kümelerle birlikte de kullanılabilir. Üstelik işlevi de aynıdır:

>>> km = set("kahramanmaraş")

>>> yedek = km.copy()

>>> yedek

set(['a', 'r', 'h', 'k', 'm', '\x9f', 'n'])

>>> km

set(['a', 'h', 'k', 'm', 'n', 'r', '\x9f'])

Burada bir şey dikkatinizi çekmiş olmalı. “km” adlı kümeyi “yedek” adıyla kopyaladık, ama bu iki kümenin çıktılarına baktığımız zaman öğe sıralamasının birbirinden farklı olduğunu görüyoruz. Bu da bize kümelerle ilgili çok önemli bir bilgi daha veriyor. Demek ki, tıpkı sözlüklerde olduğu gibi, kümeler de sırasız veri tipleriymiş. Elde ettiğimiz çıktıda öğeler rastgele diziliyor. Dolayısıyla öğelere sıralarına göre erişemiyoruz. Aynen sözlüklerde olduğu gibi...

add metodu

Kümelerden bahsederken, bunların değiştirilebilir bir veri tipi olduğunu söylemiştik. Dolayısıyla kümeler, üzerlerinde değişiklik yapmamıza müsaade eden metotlar da içerir. Örneğin add() bu tür metotlardan biridir. Add kelimesi Türkçe’de “eklemek” anlamına gelir. Adından da anlaşılacağı gibi, bu metot yardımıyla kümelerimize yeni öğeler ilave edebileceğiz. Hemen bunun nasıl kullanıldığına bakalım:

>>> kume = set(["elma", "armut", "kebap"])

>>> kume.add("çilek")

>>> print kume

set(['elma', 'armut', 'kebap', '\x87ilek'])

Gördüğünüz gibi, add() metodunu kullanarak, kümemize çilek adlı yeni bir öğe ekledik. Eğer kümede zaten varolan bir öğe eklemeye çalışırsak kümede herhangi bir değişiklik olmayacaktır. Çünkü, daha önce de söylediğimiz gibi, kümeler her bir öğeyi tek bir sayıda barındırır.

Eğer bir kümeye birden fazla öğeyi aynı anda eklemek isterseniz for döngüsünden yararlanabilirsiniz:

>>> yeni = [1,2,3]

>>> for i in yeni:
...     kume.add(i)
...

>>> kume

set([1, 2, 3, 'elma', 'kebap', '\x87ilek', 'armut'])

Burada yeni adlı listeyi kümeye for döngüsü ile ekledik. Ama bu işlemi yapmanın başka bir yolu daha vardır. Bu işlem için Python’da ayrı bir metot bulunur. Bu metodun adı update() metodudur. Sırası gelince bu metodu da göreceğiz.

difference metodu

Bu metot iki kümenin farkını almamızı sağlar. Örneğin:

>>> k1 = set([1, 2, 3, 5])
>>> k2 = set([3, 4, 2, 10])

>>> k1.difference(k2)

set([1, 5])

Demek ki k1’in k2’den farkı buymuş. Peki k2’nin k1’den farkını bulmak istersek ne yapacağız?

>>> k2.difference(k1)

set([10, 4])

Gördüğünüz gibi, birinci kullanımda, k1’de bulunup k2’de bulunmayan öğeleri elde ediyoruz. İkinci kullanımda ise bunun tam tersi. Yani ikinci kullanımda k2’de bulunup k1’de bulunmayan öğeleri alıyoruz.

İsterseniz uzun uzun difference() metodunu kullanmak yerine sadece eksi (-) işaretini kullanarak da aynı sonucu elde edebilirsiniz:

>>> k1 - k2

...veya...

>>> k2 - k1

Hayır, “madem eksi işaretini kullanabiliyoruz, o halde artı işaretini de kullanabiliriz!” gibi bir fikir doğru değildir.

difference_update metodu

Bu metot, difference() metodundan elde edilen sonuca göre bir kümenin güncellenmesini sağlar. Yani?

Hemen bir örnek verelim:

>>> k1 = set([1, 2, 3])
>>> k2 = set([1, 3, 5])

>>> k1.difference_update(k2)

set([2])

>>> print k1

set([2])

>>> print k2

set([1, 3, 5])

Gördüğünüz gibi, bu metot k1’in k2’den farkını aldı ve bu farkı kullanarak k1’i yeniden oluşturdu. k1 ile k2 arasındaki tek fark 2 adlı öğe idi. Dolayısıyla difference_update() metodunu uyguladığımızda k1’in öğelerinin silinip yerlerine 2 adlı öğenin geldiğini görüyoruz.

discard metodu

Bir önceki bölümde öğrendiğimiz add() metodu yardımıyla, önceden oluşturduğumuz bir kümeye yeni öğeler ekleyebiliyorduk. Bu bölümde öğreneceğimiz discard() metodu ise kümeden öğe silmemizi sağlayacak:

>>> hayvanlar = set(["kedi", "köpek", "at", "kuş", "inek", "deve"])

>>> hayvanlar.discard("kedi")

>>> print hayvanlar

set(['ku\x9f', 'inek', 'deve', 'k\x94pek', 'at'])

Eğer küme içinde bulunmayan bir öğe silmeye çalışırsak hiç bir şey olmaz. Yani hata mesajı almayız:

>>> hayvanlar.discard("yılan")

Burada etkileşimli kabuk sessizce bir alt satıra geçecektir. Bu metodun en önemli özelliği budur. Yani olmayan bir öğeyi silmeye çalıştığımızda hata vermemesi.

remove metodu

Bu metot da bir önceki bölümde gördüğümüz discard() metoduyla aynı işlevi yerine getirir. Eğer bir kümeden öğe silmek istersek remove() metodunu da kullanabiliriz:

>>> hayvanlar.remove("köpek")

Peki discard() varken remove() metoduna ne gerek var? Ya da tersi.

Bu iki metot aynı işlevi yerine getirse de aralarında önemli bir fark vardır. Hatırlarsanız discard() metoduyla, kümede olmayan bir öğeyi silmeye çalışırsak herhangi bir hata mesajı almayacağımızı söylemiştik. Eğer remove() metodunu kullanarak, kümede olmayan bir öğeyi silmeye çalışırsak, discard() metodunun aksine, hata mesajı alırız:

>>> hayvanlar.remove("fare")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'fare'

Bu iki metot arasındaki bu fark önemli bir farktır. Bazen yazdığımız programlarda, duruma göre her iki özelliğe de ihtiyacımız olabilir.

intersection metodu

intersection kelimesi Türkçe’de “kesişim” anlamına gelir. Adından da anladığımız gibi, intersection() metodu bize iki kümenin kesişim kümesini verecektir:

>>> k1 = set([1, 2, 3, 4])
>>> k2 = set([1, 3, 5, 7])

>>> k1.intersection(k2)

set([1, 3])

Gördüğünüz gibi, bu metot bize k1 ve k2’nin kesişim kümesini veriyor. Dolayısıyla bu iki küme arasındaki ortak elemanları bulmuş oluyoruz.

Hatırlarsanız, difference() metodunu anlatırken, difference() kelimesi yerine “-” işaretini de kullanabileceğimiz, söylemiştik. Benzer bir durum intersection() metodu için de geçerlidir. İki kümenin kesişimini bulmak için “&” işaretinden yararlanabiliriz:

>>> k1 & k2

set([1, 3])

Python programcıları genellikle uzun uzun intersection yazmak yerine “&” işaretini kullanırlar...

İsterseniz bu metot için örnek bir program verelim. Böylece gerçek hayatta bu metodu nasıl kullanabileceğimizi görmüş oluruz:

# -*- coding: utf-8 -*-

tr = "şçöğüıŞÇÖĞÜİ"

parola = raw_input("Sisteme giriş için bir parola belirleyin: ")

if set(tr) & set(parola):
    print "Parolanızda Türkçe harfler kullanmayın!"

else:
    print "Parolanız kabul edildi!"

Burada eğer kullanıcı, parola belirlerken içinde Türkçe bir harf geçen bir kelime yazarsa programımız kendisini Türkçe harf kullanmaması konusunda uyaracaktır. Bu kodlarda kümeleri nasıl kullandığımıza dikkat edin. Programda asıl işi yapan kısım şu satırdır:

if set(tr) & set(parola):
    print "Parolanızda Türkçe harfler kullanmayın!"

Burada aslında şöyle bir şey demiş oluyoruz:

Eğer set(tr) ve set(parola) kümelerinin kesişim kümesi boş değilse, kullanıcıya “Parolanızda Türkçe harfler kullanmayın!” uyarısını göster!

set(tr) ve set(parola) kümelerinin kesişim kümesinin boş olmaması, kullanıcının girdiği kelime içindeki harflerden en az birinin tr adlı değişken içinde geçtiği anlamına gelir. Burada basitçe, tr değişkeni ile parola değişkeni arasındaki ortak öğeleri sorguluyoruz. Eğer kullanıcı herhangi bir Türkçe harf içermeyen bir kelime girerse set(tr) ve set(parola) kümelerinin kesişim kümesi boş olacaktır. İsterseniz küçük bir deneme yapalım:

>>> tr = "şçöğüıŞÇÖĞÜİ"

>>> parola = "çilek"

>>> set(tr) & set(parola)

set(['ç'])

Burada kullanıcının “çilek” adlı kelimeyi girdiğini varsayıyoruz. Böyle bir durumda set(tr) ve set(parola) kümelerinin kesişim kümesi “ç” harfini içerecek, dolayısıyla da programımız kullanıcıya uyarı mesajı gösterecektir. Eğer kullanıcımız “kalem” gibi Türkçe harf içermeyen bir kelime girerse:

>>> tr = "şçöğüıŞÇÖĞÜİ"

>>> parola = "kalem"

>>> set(tr) & set(parola)

set([])

Gördüğünüz gibi, elde ettiğimiz küme boş. Dolayısıyla böyle bir durumda programımız kullanıcıya herhangi bir uyarı mesajı göstermeyecektir.

intersection() metodunu pek çok yerde kullanabilirsiniz. Hatta iki dosya arasındaki benzerlikleri bulmak için dahi bu metottan yararlanabilirsiniz. İlerde dosya işlemleri konusunu işlerken bu metottan nasıl yararlanabileceğimizi de anlatacağız.

intersection_update metodu

Hatırlarsanız difference_update() metodunu işlerken şöyle bir şey demiştik:

Bu metot, difference() metodundan elde edilen sonuca göre bir kümenin güncellenmesini sağlar.

İşte intersection_update metodu da buna çok benzer bir işlevi yerine getirir. Bu metodun görevi, intersection() metodundan elde edilen sonuca göre bir kümenin güncellenmesini sağlamaktır:

>>> k1 = set([1, 2, 3])
>>> k2 = set([1, 3, 5])

>>> k1.intersection_update(k2)

set([1, 3])

>>> print k1

set([1, 3])

>>> print k2

set([1, 3, 5])

Gördüğünüz gibi, intersection_update() metodu k1’in bütün öğelerini sildi ve yerlerine k1 ve k2’nin kesişim kümesinin elemanlarını koydu.

isdisjoint metodu

Bu metodun çok basit bir görevi vardır. isdisjoint() metodunu kullanarak iki kümenin kesişim kümesinin boş olup olmadığı sorgulayabilirsiniz. Hatırlarsanız aynı işi bir önceki bölümde gördüğümüz intersection() metodunu kullanarak da yapabiliyorduk. Ama eğer hayattan tek beklentiniz iki kümenin kesişim kümesinin boş olup olmadığını, yani bu iki kümenin ortak eleman içerip içermediğini öğrenmekse, basitçe isdisjoint() metodundan yararlanabilirsiniz:

>>> a = set([1, 2, 3])
>>> b = set([2, 4, 6])

>>> a.isdisjoint(b)

False

Gördüğünüz gibi, a ve b kümesinin kesişimi boş olmadığı için, yani bu iki küme ortak en az bir öğe barındırdığı için, isdisjoint() metodu False çıktısı veriyor. Burada temel olarak şu soruyu sormuş oluyoruz:

a ve b ayrık kümeler mi?

Python da bize cevap olarak, “Hayır değil,” anlamına gelen False çıktısını veriyor... Çünkü a ve b kümelerinin ortak bir elemanı var (2).

Bir de şuna bakalım:

>>> a = set([1, 3, 5])
>>> b = set([2, 4, 6])

>>> a.isdisjoint(b)

True

Burada a ve b kümeleri ortak hiç bir elemana sahip olmadığı için “Doğru” anlamına gelen True çıktısını elde ediyoruz.

issubset metodu

Bu metot yardımıyla, bir kümenin bütün elemanlarının başka bir küme içinde yer alıp yer almadığını sorgulayabiliriz. Yani bir kümenin, başka bir kümenin alt kümesi olup olmadığını bu metot yardımıyla öğrenebiliriz. Eğer bir küme başka bir kümenin alt kümesi ise bu metot bize True değerini verecek; eğer değilse False çıktısını verecektir:

>>> a = set([1, 2, 3])
>>> b = set([0, 1, 2, 3, 4, 5])

>>> a.issubset(b)

True

Bu örnekte True çıktısını aldık, çünkü a kümesinin bütün öğeleri b kümesi içinde yer alıyor. Yani a, b‘nin alt kümesidir.

issuperset metodu

Bu metot, bir önceki bölümde gördüğümüz issubset() metoduna benzer. Matematik derslerinde gördüğümüz “kümeler” konusunda hatırladığınız “b kümesi a kümesini kapsar” ifadesini bu metotla gösteriyoruz. Önce bir önceki derste gördüğümüz örneğe bakalım:

>>> a = set([1, 2, 3])
>>> b = set([0, 1, 2, 3, 4, 5])

>>> a.issubset(b)

True

Buradan, “a kümesi b kümesinin alt kümesidir,” sonucuna ulaşıyoruz. Bir de şuna bakalım:

>>> a = set([1, 2, 3])
>>> b = set([0, 1, 2, 3, 4, 5])

>>> b.issuperset(a)

True

Burada ise, “b kümesi a kümesini kapsar,” sonucunu elde ediyoruz. Yani b kümesi a kümesinin bütün elemanlarını içinde barındırıyor.

union metodu

union() metodu iki kümenin birleşimini almamızı sağlar. Hemen bir örnek verelim:

>>> a = set([2, 4, 6, 8])
>>> b = set([1, 3, 5, 7])

>>> a.union(b)

{1, 2, 3, 4, 5, 6, 7, 8}

Önceki bölümlerde gördüğümüz bazı metotlarda olduğu gibi, union() metodu da bir kısayola sahiptir. union() metodu yerine “|” işaretini de kullanabiliriz:

>>> a | b

union() metodu yerine, bu metodun kısayolu olan “|” işareti Python programcıları tarafından daha sık kullanılır.

update metodu

Hatırlarsanız add() metodunu anlatırken şöyle bir örnek vermiştik:

>>> kume = set(["elma", "armut", "kebap"])

>>> yeni = [1, 2, 3]

>>> for i in yeni:
...     kume.add(i)
...

set([1, 2, 3, 'elma', 'kebap', '\x87ilek', 'armut'])

Bu örneği verdikten sonra da şöyle bir şey demiştik:

“Burada yeni adlı listeyi kümeye for döngüsü ile ekledik. Ama bu işlemi yapmanın başka bir yolu daha vardır. Bu işlem için Python’da ayrı bir metot bulunur.”

İşte bu metodu öğrenmenin vakti geldi. Metodumuzun adı update(). Bu metot, bir kümeyi güncellememizi sağlar. İsterseniz yukarıdaki örneği, bu metodu kullanarak tekrar yazalım:

>>> kume = set(["elma", "armut", "kebap"])

>>> yeni = [1, 2, 3]

>>> kume.update(yeni)

>>> print kume

{1, 2, 3, 'elma', 'kebap', 'armut'}

Gördüğünüz gibi, for döngüsünü kullanmaya gerek kalmadan aynı sonucu elde edebildik.

symmetric_difference metodu

Daha önceki bölümlerde difference() metodunu kullanarak iki küme arasındaki farklı öğeleri bulmayı öğrenmiştik. Örneğin elimizde şöyle iki küme var diyelim:

>>> a = set([1, 2, 5])
>>> b = set([1, 4, 5])

Eğer a kümesinin b kümesinden farkını bulmak istersek şöyle yapıyoruz:

>>> a.difference(b)

set([2])

Demek ki a kümesinde bulunup b kümesinde bulunmayan öğe 2 imiş.

Bir de b kümesinde bulunup a kümesinde bulunmayan öğelere bakalım:

>>> b.difference(a)

set([4])

Bu da bize “4” çıktısını verdi. Demek ki bu öğe b kümesinde bulunuyor, ama a kümesinde bulunmuyormuş. Peki ya kümelerin ikisinde de bulunmayan öğeleri aynı anda nasıl alacağız? işte bu noktada yardımımıza symmetric_difference() adlı metot yetişecek:

>>> a.symmetric_difference(b)

set([2, 4])

Böylece iki kümede de bulunmayan öğeleri aynı anda almış olduk.

symmetric_difference_update metodu

Daha önce difference_update ve intersection_update gibi metotları öğrenmiştik. symmetric_difference_update() metodu da bunlara benzer bir işlevi yerine getirir:

>>> a = set([1,2, 5])

>>> b = set([1,4, 5])

>>> a.symmetric_difference_update(b)

>>> print a

set([2, 4])

Gördüğünüz gibi, a kümesinin eski öğeleri gitti, yerlerine symmetric_difference() metoduyla elde edilen çıktı geldi. Yani a kümesi, symmetric_difference() metodunun sonucuna göre güncellenmiş oldu...

pop metodu

İnceleyeceğimiz son metot pop() metodu olacak. Gerçi bu metot bize hiç yabancı değil. Bu metodu listeler konusundan hatırlıyoruz. Orada öğrendiğimize göre, bu metot listenin bir öğesini silip ekrana basıyordu. Aslında buradaki fonksiyonu da farklı değil. Burada da kümelerin öğelerini silip ekrana basıyor:

>>> a = set(["elma", "armut", "kebap"])

>>> a.pop()

'elma'

Peki bu metot hangi ölçüte göre kümeden öğe siliyor? Herhangi bir ölçüt yok. Bu metot, küme öğelerini tamamen rastgele siliyor.

Böylelikle Python’da Listeler, Demetler, Sözlükler ve Kümeler konusunu bitirmiş olduk. Bu konuları sık sık tekrar etmek, hiç olmazsa arada sırada göz gezdirmek bazı şeylerin zihnimizde yer etmesi açısından oldukça önemlidir.

Dondurulmuş Kümeler (Frozenset)

Daha önce de söylediğimiz gibi, kümeler üzerinde değişiklik yapabiliyoruz. Zaten kümelerin add() ve remove() gibi metotlarının olması bu durumu teyit ediyor. Ancak kimi durumlarda, öğeleri üzerinde değişiklik yapılamayan kümelere de ihtiyaç duyabilirsiniz. Hatırlarsanız listeler ve demetler arasında da buna benzer bir ilişki var. Demetler çoğu zaman, üzerinde değişiklik yapılamayan bir liste gibi davranır. İşte Python aynı imkanı bize kümelerde de sağlar. Eğer öğeleri üzerinde değişiklik yapılamayan bir küme oluşturmak isterseniz set() yerine frozenset() fonksiyonunu kullanabilirsiniz. Dilerseniz hemen bununla ilgili bir örnek verelim:

>>> dondurulmus = frozenset(["elma", "armut", "ayva"])

Dondurulmuş kümeleri bu şekilde oluşturuyoruz. Şimdi bu dondurulmuş kümenin metotlarına bakalım:

>>> dir(dondurulmus)

['__and__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__',
'__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__',
'__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__',
'__subclasshook__', '__xor__', 'copy', 'difference', 'intersection',
'isdisjoint', 'issubset', 'issuperset', 'symmetric_difference', 'union']

Gördüğünüz gibi, add(), remove(), update() gibi, değişiklik yapmaya yönelik metotlar listede yok.

Dondurulmuş kümeler ile normal kümeler arasında işlev olarak hiçbir fark yoktur. Bu ikisi arasındaki fark, listeler ile demetler arasındaki fark gibidir.

Bölüm Soruları

1. Liste, demet, sözlük ve kümeleri karşılaştırdığınızda, bu veri tiplerini oluşturma bakımından kümelerle öteki veri tipleri arasında nasıl bir fark görüyorsunuz?

2. Bir küme içinde herhangi bir öğenin bulunup bulunmadığını nasıl sorgulayabileceğimizi gösteren bir örnek kod yazın.

3. Karakter dizilerini, demetleri ve listeleri kullanarak küme oluşturabiliyoruz. Ancak aynı şeyi sayıları kullanarak yapamıyoruz. Sayılardan küme oluşturmak istediğimizde şöyle bir hata mesajı veriyor bize Python:

>>> a = 10

>>> set(a)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

Burada Python bize kabaca şöyle bir şey söylemiş oluyor: “Sayılar üzerinde döngü kurulamaz!”. Aldığınız bu hata mesajının anlamı üzerinde düşünün. Bu hatayı başka hangi durumlarda alırsınız?

4. Kullanıcıya renk adları soran bir program yazın. Kullanıcıdan gelen renk adlarını programın sonunda kullanıcıya bildirin. Ancak kullanıcının girdiği her renk adı kendisine bir kez bildirilmeli, yani renk adları tekrar etmemeli.

5. Demetler bölümünde şöyle bir soru sormuştuk:

Diyelim ki elimizde şöyle bir liste var:

liste = ["elma", "armut", "elma", "kiraz",
         "çilek", "kiraz", "elma", "kebap"]

Bu listedeki her bir öğenin, listede kaç kez geçtiğini söyleyen bir program yazın. Programınız tam olarak şöyle bir çıktı vermeli:

elma öğesi listede 3 kez geçiyor!
armut öğesi listede 1 kez geçiyor!
kiraz öğesi listede 2 kez geçiyor!
çilek öğesi listede 1 kez geçiyor!
kebap öğesi listede 1 kez geçiyor!

Kümeler bölümünde öğrendiğiniz bilgileri de dikkate alarak bu programı yeniden yazın.