Bir text ifadesindeki türkçe karakterleri, sözlük yapılarından yararlanarak İngilizce karaktere çevirip bastırmak

Konuya girmeden önce :

Ben Python’u öğrenirken, dokümantasyon okumuyordum ki bir yazılım dili öğrenirken bu çok önemli bir şey. Fakat ben bunun değerini öğrendim. Sadece udemy üzerinden öğrendiklerimi devamlı olarak uygulaya uygulaya öğrenmeye çalıştım. Keşke yazbel’in Türkçe python dokümantasyonundan zamanında haberdar olsaydım diyorum şimdi.
Udemy üzerinden aldığım eğitim seti de kötü bir tercih oldu. Daha çok ezbere dayalı bir anlatıma maruz kaldığım için sıkıntılar çekiyorum.

söylediklerim dolayısıyla, python’da kesinlikle bilinmesi gereken bir takım şeyler bende eksik.

Bayağıdır, yazbelin Python belgelendirmesini okuyarak Python’u bir kere daha öğrenmeye çalıştım ve python’la yaptığım tek bir projede dahi kullanmadığım sözlük yapıları üzerinde durmaya karar verdim.

blocked_letters = {
    "ç" : "c",
    "ğ" : "g",
    "ı" : "i",
    "ö" : "o",
    "ş" : "s",
    "ü" : "u",
}


text = "türkçe yazı yazıyorum. ürünler kelimesinin içinde türkçe karakter vardır."

yasak_harfler = []

blocked_letters_in_text = []

for i in blocked_letters.keys():
    yasak_harfler.append(i)
    
for i in text:
    if i in yasak_harfler:
        blocked_letters_in_text.append(i)
        
print(blocked_letters_in_text)
        

 #      Çıktı --> ['ü', 'ç', 'ı', 'ı', 'ü', 'ü', 'ç', 'ü', 'ç', 'ı']

sözlükleri kurcalamak adına şöyle bir şeyler denedim. Burada, oluşturduğum textin içindeki türkçe karakterleri, sözlük yapısı aracılığıyla taramaya çalıştım.

başarılı da oldu. Fakat daha sonra aklıma şu geldi. Bu textteki türkçe karakterleri, ingilizce karakterler olacak şekilde değiştirip geri bastırabilir miyim ? Bunu düşündüm ancak nasıl yapabileceğim hakkında bir fikrim yok. Bunu nasıl yapabilirim ?

Son olarak;

Ben daha önce arayüzlü, basit bir hesap makinesi yapmaya çalışmıştım ve üslü sayı hesaplaması için yazbel ailesinden yardım almıştım. Burada da sözlük yapısı kullanılmıştı fakat anlamamıştım.
Bana onun mantığını da açıklayabilir misiniz ?

superscript = {

    "0": "\u2070",

    "1": "\u00b9",

    "2": "\u00b2",

    "3": "\u00b3",

    "4": "\u2074",

    "5": "\u2075",

    "6": "\u2076",

    "7": "\u2077",

    "8": "\u2078",

    "9": "\u2079"

}

        def get_superscript(x):

            return "".join(superscript[i] for i in str(x))

    

        def exponential_expression(x):

            count = 2

            while (y := math.log(x, count)) != int(y):

                count += 1

            return f"{count}{get_superscript(int(y))}"

        

        try:

            

            d = self.lineEdit.text()

            self.lineEdit.setText(exponential_expression(x=int(d)))

            

        except ValueError:

            self.lineEdit.setText("Geçersiz İşlem")

                    

        self.label_2.setText(self.lineEdit.text())

Buradan da gördüğüm üzere sözlük yapısının gerçekten önemli bir şey olduğunu görüyorum. Bunu anlamak için de sizlerden birazcık yardım istiyorum.

Kodların tam hali burada

birincisi için dicem dediğin gibi bunu nasıl geri döndüreceksin yani benm kullandığım bi yöntem var ama daha iyisi de olablr warsa söyleyn lütfen. ben
blocked_letters = { "ç" : "%6", "ğ" : "%5", "ı" : "%4", "ö" : "%3", "ş" : "%2", "ü" : "%1", }
tabii siz bunu başka bi şekilde editlersiniz %1 fln fazla kullanılablr yani başka az kullanlan bir karakter mantığı seçersnz sonra for blocked_letters.keys ile dolaşıp text = text.replace(blocked_letters[i]) i felan bi şeyler yaparsın geri dönünderme işlemi için de tam tersi

Döndürmek istediğiniz şey keyler mi ? Yoksa valueler mi ?
İkisini de for döngüsüyle alabiliyoruz zaten kolay bir şekilde.

c den ç ye nasıl geri döndüreceksiniz demek istemiştim sonuçta c harfi türkçede de var tüm c leri ç ye değiştirme ihtimalin var ona demiştn

ya da tüm bu harflerinden ziyade bir de indexlerini bir listede tutman da çözm olurdu gerçi

Sözlükler belgelerde de anlatıldığı üzere “mapping” denilen, aynı olması gerekmeyen iki veri tipine ait elemanları birbirine eşleyen bir başka veri yapısıdır. Yani bir nevi fonksiyondurlar, iki sonlu küme arasında kullanıcının belirttiği eşlemeyi temsil ederler.

:'nın solundakiler tanım kümesindeki elemanlara, sağındakiler ise değer kümesindeki elemanlara tekabül ediyor. Python’da değer kümesine koyabileceğiniz veri tipi üzerine herhangi bir sınırlama yok - ne isterseniz koyabilirsiniz: str, list, dict, tuple, complex veya kendi yazdığınız herhangi bir sınıfın örnekleri. Solundaki elemanların ise hashable olması şart koşuluyor, yani __hash__ ve __eq__ metotlarına uygun bir şekilde sahip olması gerekiyor (örneğin str, int, float, tuple* gibi tipler hashable, ama mesela list değil).

Belgelerde çok daha iyi bir anlatımı var ve "neden kullanmalıyız"a cevabı da oradadır ama, en öne çıkan özelliklerinden bir tanesi bir değerin mevcudiyetinin kontrolünün O(1) zamanlı olması yani tabir-i caizse anlık karar verebilme. Bu, listelerde O(N)e tekabül ediyor, N listenin uzunluğu. Bu “O” notasyonuna gerekli yerlerden bakarsınız ama aşağı yukarı şöyle düşünebilirsiniz: elimizdeki bir değerin verilen bir listede olup olmadığını anlamak için ortalama senaryoda elemanların yarısına kadar listeyi gezmemiz gerekir, ancak sözlüğün içerisinde arıyorsak “tak” diye olup olmadığını anlayabiliyoruz, bu da hashing sayesinde.

Buradan hareketle

şeklinde bir kullanım sözlüklerin doğasına çok ters düşmekte. Bunun yerine

for harf in text:
    if harf in blocked_letters:
        ...

şeklinde direkt sözlük üzerinden eleman bulunup bulunmama durumunu kontrol etmeliyiz. (Tabii bu for - if - append basamakları list-comprehension’ı çağırıyor, orayı halledersiniz.)

Yine harf-harf bir for dönersiniz. Eğer ilgili harf blocked_letttersa aitse, blocked_letters’ta bu harfe “karşılık” gelen harfi bastırırsınız. Eğer değilse…

Veya, str.maketrans/translate var, ama ilkini yapsanız sözlüklerle aranız daha iyi olur.

Tekrarlayayım, belgelerde çok daha iyi bir anlatımı var, oraya bir göz attıktan sonra yazdığınız kodu tekrar yazabilirsiniz ve istediğiniz eklemeyi gerçekleştirebilirsiniz, şu kısmı da anlamak dahil (her ne kadar yazan kişi çok yorum yazmamış olsa da!)


*: hashable olmayan tip içeren tuple'lar makul bir şekilde hashable sayılmıyormuş :d örn. (4, 7, [-5, -1])

Belgelerde “immutability” şart koşulmuş ama “hashable” olması gerek aslında diye düşünüyorum, zira bu unhashable içeren tuple bir örnek teşkil edebilir. Ama o da artık immutable’lıktan çıkmış mıdır… Yine de hashable olup immutable olmayan bir custom class yazılabilir heralde, bilemiyorum…

Burası hatalı. id operatörü overwrite (üstüne yazılabilir?) edilebilir değil, __id__ de özel bir metot değil. Hashable olmak için __hash__ ve __eq__ metotları yeterli.

Glossary’den:

An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method). Hashable objects which compare equal must have the same hash value.


Linked list’ler hakkında konuşuluyorsa indise erişmek O(N). Python list sınıfı için linked list değil array kullanıyor, yani indise erişim O(1) (kaynak).

Yukarıda da bundan mı bahsetmiştiniz? Ben anahtar veya indisi kullanarak değere erişmeyi kastettiğinizi düşündüm.


tuple ve frozenset gibi container’lar kendi hash değerlerini elemanlarının hash değerlerine göre hesaplıyor. Mutable container’ların __hash__ impleme etmeme sebebi bu, aksi takdirde container’ın hash değeri elemanları ile birlikte değişebilir. Aynı şey mutable bir container içeren immutable container’lar için de geçerli.

Daha önce mutable container’ların id’lerinin hash gibi kullanıldığını görmüştüm ama CPython’da bu ne kadar geçerli bilmiyorum. Tabii bunu da sadece o nesnenin kendisi için kullabiliriz:

>>> d = {}
>>> a = [1, 2]
>>> d[id(a)] = 1
>>> d[id(a)]
1
>>> b = [1, 2]
>>> d[id(b)]
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    d[id(b)]
KeyError: 2985730339456
>>> 

Normalde x == b, d[x] == d[b]'yi gerektirir.

1 Beğeni

teşekkürler, düzelttim.

evet, teşekkürler, düzelttim.

tuple’a unhashable koyabiliyoruz, ama frozenset’e unhashable koyamıyoruz, değil mi?

list __hash__ metodunu implement etmiyor mu?

Sorularım şunlar:

t = (4, 7, [-5, -1]) immutable mı?

immutability hashability’yi kapsıyor mu?

Doğru, set ve frozenset zaten içindeki elemanların hashable olmasını istiyor.

Hayır, etmiyor:

>>> list.__hash__ == None
True
>>> 

Evet.

“Hashable nesneler, immutable nesnelerin alt kümesi mi” diye mi soruyorsunuz? Bu bütün hashable nesnelerin immutable olması demek, eğer bizim tanımladığımız sınıfları mutable sayarsak (sanırım öyle sayılıyor ama belgelerde buna rastlamadım) bu yanlış.

Bu arada bizim tanımladığımız sınıfların örnekleri hash’ları için id’lerini kullanıyormuş, yani yukarıda yazdığım çözüm geçerli gibi duruyor. Tabii dediğim gibi x == b => d[x] == d[b] durumu var, bizim tanımladığımız sınıflarda bu geçerli iken builtin immutable’larda değil.

1 Beğeni

Peki bu neden True dönüyor onu anlamadım:

hasattr([44], "__hash__")

They play an important role in places where a constant hash value is needed, for example as a key in a dictionary.

Buradan immutable olmadığını anlamamız gerekmiyor mu?

evet, teşekkürler.

Bu tek yönlü, değil mi? Yani d[x] == d[b] => x == b doğru olmak zorunda değil, yani bire-birlik dayatılmıyor?

>>> [44].__hash__ == None
True
>>> 

Kavramlar üzerine bu kadar tartışmaya gerek var mı bilmiyorum, tek yaptığımız orada yazanlar üzerine düşünmek. Benim bildiğim bütün tuple’lar immutable ama hepsi hashable değil.

Doğru, düzeltiyorum.

2 Beğeni