Python’daki sürpriz yumurtalar içinde en bilineni herhalde şudur:
Bu komutu verdiğinizde, Python’un felsefesini anlatan bir metin görürsünüz:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!
Ancak “this” modülü yukarıdaki metinden ibaret değildir. Bu modülün başka özellikleri de bulunur. Peki nedir bu özellikler?
Yukarıdaki çıktıyı veren “this” adlı modülün içeriğine baktığımızda şöyle bir şeyle karşılaşıyoruz:
>>> dir(this)
['__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'c', 'd', 'i', 's']
Demek ki “this” modülünün içinde “c”, “d”, “i” ve “s” adlı dört adet nitelik var. Ben bu yazıda sizin dikkatinizi “s” ve “d” niteliklerine çekmek istiyorum.
Önce “this” modülünün “s” niteliğini kontrol edelim:
>>> this.s
"Gur Mra bs Clguba, ol Gvz Crgref\n\nOrnhgvshy vf
orggre guna htyl.\nRkcyvpvg vf orggre guna
vzcyvpvg.\nFvzcyr vf orggre guna pbzcyrk.\nPbzcyrk
vf orggre guna pbzcyvpngrq.\nSyng vf orggre guna
arfgrq.\nFcnefr vf orggre guna qrafr.\nErnqnovyvgl
pbhagf.\nFcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx
gur ehyrf.\nNygubhtu cenpgvpnyvgl orngf chevgl.
\nReebef fubhyq arire cnff fvyragyl.\nHayrff rkcyvpvgyl
fvyraprq.\nVa gur snpr bs nzovthvgl, ershfr gur grzcgngvba
gb thrff.\nGurer fubhyq or bar-- naq cersrenoyl bayl bar
--boivbhf jnl gb qb vg.\nNygubhtu gung jnl znl abg or boivbhf
ng svefg hayrff lbh'er Qhgpu.\nAbj vf orggre guna arire.
\nNygubhtu arire vf bsgra orggre guna *evtug* abj.\nVs
gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
\nVs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n
tbbq vqrn.\nAnzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f
qb zber bs gubfr!"
Karşımıza anlamsız gibi görünen bir karakter dizisi çıktı… Aslında bu karmaşık ve anlamsız görünen kelime yumağının, en başta verdiğimiz “The Zen of Python” adlı metnin “şifrelenmiş” hali olduğunu az çok tahmin edebiliyoruz. Peki bundan nasıl emin olabiliriz?
Herhangi bir adım atmadan önce bir de “this” modülünün “d” niteliğine bakalım:
>>> this.d
{'A': 'N', 'C': 'P', 'B': 'O', 'E': 'R', 'D': 'Q', 'G': 'T',
'F': 'S', 'I': 'V', 'H': 'U', 'K': 'X', 'J': 'W', 'M': 'Z',
'L': 'Y', 'O': 'B', 'N': 'A', 'Q': 'D', 'P': 'C', 'S': 'F',
'R': 'E', 'U': 'H', 'T': 'G', 'W': 'J', 'V': 'I', 'Y': 'L',
'X': 'K', 'Z': 'M', 'a': 'n', 'c': 'p', 'b': 'o', 'e': 'r',
'd': 'q', 'g': 't', 'f': 's', 'i': 'v', 'h': 'u', 'k': 'x',
'j': 'w', 'm': 'z', 'l': 'y', 'o': 'b', 'n': 'a', 'q': 'd',
'p': 'c', 's': 'f', 'r': 'e', 'u': 'h', 't': 'g', 'w': 'j',
'v': 'i', 'y': 'l', 'x': 'k', 'z': 'm'}
“d” niteliği ise, anahtarları ve değerleri alfabetik karakterler olan bir sözlük barındırıyor. Gördüğünüz gibi bu sözlükte belli harfler belli harflerle eşleştirilmiş.
Bu alfabetik sözlüğün de yukarıdaki şifreli metinle bir bağlantısı olduğunu kestirmek çok zor değil. Hemen bir kaç deneme yapalım:
>>> this.d[this.s[0]]
'T'
Burada this.s adlı karmaşık karakter dizisinin ilk harfini this.d adlı sözlüğe anahtar olarak verdik. this.s karakter dizisinin ilk harfi “G”. Dolayısıyla şöyle bir şey yapmış olduk:
Tabii this.d sözlüğünde “G” harfinin karşılığı “T” harfi olduğu için çıktıda “T” harfini aldık. O halde şöyle bir şey yazabiliriz:
>>> for i in this.s:
... print this.d[i]
Buradan şöyle bir çıktı alırız:
T
h
e
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyError: ' '
Bu çıktı bize iki önemli bilgi verdi:
Birincisi, şifreli metnin ilk kelimesini elde ettik. Buna göre ilk kelime “The”. Yani doğru yoldayız!
İkincisi, sözlükte sadece alfabe harfleri olduğu için, for döngüsü bir boşluk karakteriyle karşılaştığında doğal olarak KeyError hatası veriyor. Yani kelimeleri birbirinden ayıran boşluk karakterlerinin ve hatta satırları bitiren “yeni satır” (newline — \n) karakterlerinin icabına bakmamız gerekiyor. Bunun için şöyle bir şey yazılabilir:
>>> a = ""
>>> for i in this.s:
... try:
... a += this.d[i]
... except KeyError as k:
... a += str(k)
...
>>> print a
Burada öncelikle a adlı boş bir karakter dizisi tanımladık. Biraz sonra bir for döngüsü ile alacağımız bütün harfleri bu a adlı karakter dizisi içinde toplayacağız.
Sonraki satırda for döngümüzü yazıyoruz. Burada yaptığımız şey şu: this.s adlı karakter dizisi içindeki bütün karakterleri tek tek this.d sözlüğü içinde sorgulayıp, hepsini a adlı karakter dizisine atıyoruz. Ancak this.s adlı karakter dizisi içinde, this.d adlı sözlükte herhangi bir karşılığı olmayan boşluk ve yeni satır karakterleri de olduğu için, KeyError hatası alma ihtimaline karşı, hata veren bütün karakterleri de tek tek a adlı karakter dizisine gönderiyoruz. Böylece şifreli karakter dizisi içindeki bütün boşlukları ve satır başlarını muhafaza etmiş oluyoruz. Eğer bu boşluk ve satır başlarını a karakter dizisine göndermek yerine mesela pass gibi bir deyimle görmezden gelirsek şifreli metindeki boşlukları ve satır başlarını kaybetmiş oluruz. O zaman a adlı karakter dizisindeki bütün harfler çıktıda birbirine bitişik görüneceği için yine anlaşılması zor bir metin ortaya çıkmış olur…
Son olarak da a adlı karakter dizisini ekrana yazdırıyoruz…
Bakalım bu kodlar bize ne çıktı veriyor:
The’ ‘Zen’ ‘of’ ‘Python’,” ‘by’ ‘Tim’ ‘Peters’\n”
\n’Beautiful’ ‘is’ ‘better’ ‘than’ ‘ugly’.”\n’Explicit’
‘is’ ‘better’ ‘than’ ‘implicit’.”\n’Simple’ ‘is’ ‘better’
‘than’ ‘complex’.”\n’Complex’ ‘is’ ‘better’ ‘than’
‘complicated’.”\n’Flat’ ‘is’ ‘better’ ‘than’ ‘nested’.
”\n’Sparse’ ‘is’ ‘better’ ‘than’ ‘dense’.”\n’Readability’
‘counts’.”\n’Special’ ‘cases’ ‘aren”‘”t’ ‘special’ ‘enough’
‘to’ ‘break’ ‘the’ ‘rules’.”\n’Although’ ‘practicality’ ‘beats’ ‘purity’.”\n’Errors’ ‘should’ ‘never’ ‘pass’ ‘silently’.
”\n’Unless’ ‘explicitly’ ‘silenced’.”\n’In’ ‘the’ ‘face’ ‘of’
‘ambiguity’,” ‘refuse’ ‘the’ ‘temptation’ ‘to’ ‘guess’.
”\n’There’ ‘should’ ‘be’ ‘one’-”-” ‘and’ ‘preferably’
‘only’ ‘one’ ”-”-’obvious’ ‘way’ ‘to’ ‘do’ ‘it’.”\n’Although’
‘that’ ‘way’ ‘may’ ‘not’ ‘be’ ‘obvious’ ‘at’ ‘first’ ‘unless’
‘you”‘”re’ ‘Dutch’.”\n’Now’ ‘is’ ‘better’ ‘than’ ‘never’.
”\n’Although’ ‘never’ ‘is’ ‘often’ ‘better’ ‘than’ ”*’right’*”
‘now’.”\n’If’ ‘the’ ‘implementation’ ‘is’ ‘hard’ ‘to’ ‘explain’,
” ‘it”‘”s’ ‘a’ ‘bad’ ‘idea’.”\n’If’ ‘the’ ‘implementation’ ‘is’
‘easy’ ‘to’ ‘explain’,” ‘it’ ‘may’ ‘be’ ‘a’ ‘good’ ‘idea’.
”\n’Namespaces’ ‘are’ ‘one’ ‘honking’ ‘great’ ‘idea’
”-”-” ‘let”‘”s’ ‘do’ ‘more’ ‘of’ ‘those’!’
Bingo! Böylece şifreli metni çözmüş olduk…
Şifreli metni çözmemizi sağlayan kodları aslında şu şekilde de yazabilirdik:
>>> a = ""
>>> for i in this.s:
... a += this.d.get(i, i)
...
>>> print a
Gördüğünüz gibi, bu defaki çıktımız çok daha zarif…
Burada Python sözlüklerinin get() metodunu kullandık. Bu sayede try…except bloklarıyla uğraşmamıza da gerek kalmadı. get() metodunun ikinci argümanı sayesinde, sözlükte bulunamadığı için hata veren boşluk ve yeni satır karakterlerinin doğrudan a değişkenine eklenmesini sağladık. Bu get() metodunun nasıl çalıştığını daha iyi anlamak için http://www.istihza.com/py2/sozluk.html#get-ve-has-key adresini ziyaret edebilirsiniz.
İyi çalışmalar,
istihza Python get metodu, Python, şifreli metin, sürpriz yumurta, this modülü
Son Yorumlar