arşiv

yazılar buna göre etiketlendi; ‘sürpriz yumurta’

this Modülü İçindeki Şifreli Metin

Çarşamba, 16 Haz 2010

Python’daki sürpriz yumurtalar içinde en bilineni herhalde şudur:

>>> import this

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:

>>> this.d["G"]

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,

Python , , , ,

Sürpriz Yumurtalar

Pazar, 11 Eki 2009

Daha önce bir forumda bahsetmiştim. Burada da paylaşmak istedim…

OpenOffice içinde çok hoş bir sürpriz yumurta var. OpenOffice Calc (SpreadSheet — Hesap Tablosu) programını açın. Orada herhangi bir hücreye şunu yazın:

=Game(“StarWars”)

Enter’e bastıktan sonra karşınıza Atari döneminden kalma keyifli bir oyun çıkacak. :) Ben bu oyunu uzun zamandır kafa dağıtmak için oynuyorum. Size de tavsiye ederim.

Benzer bir oyun GNOME içinde de bulunuyormuş. Bunu da bir sitede gördüm. ALT+F2 tuşlarına basıp açılan ekranda şu komutu verin:

gegls from outer space

İyi eğlenceler!.. :)

GNU/Linux , , ,

Python 3.0′da bir sürpriz yumurta…

Perşembe, 07 May 2009

Python 3.0 yeni özelliklerin yanısıra birkaç sürpriz yumurta da getiriyor beraberinde… Ben de bu yazıda bu “hoşluk”lardan birini sizinle paylaşayım istedim.

Şimdi Python 3.0′ın etkileşimli kabuğunu açıyoruz ve şu komutu veriyoruz:

import antigravity

Bu komutun çalışması için elbette bir internet bağlantınızın olması gerekiyor…

İyi eğlenceler… :)

Bu arada bu modülü aynı etkileşimli kabuk oturumu içinde tekrar içe aktarmak isterseniz şu komutları kullanmanız gerekiyor:

import imp
imp.reload(antigravity)

Buradan anladığınız gibi, artık Python 3.0′da “reload()” diye bir fonksiyon yok!… Daha önce içe aktardığımız bir modülü tekrar içe aktarmak istediğimizde reload() yerine imp.reload() diyeceğiz… Tabii aynı oturum içinde bir kez “import imp” demek yeterli olacaktır. “imp” modülünü bir kez içe aktardıktan sonra, yeniden yüklemek istediğimiz modüller için yalnızca “imp.reload(modül_adı)” kalıbını kullanmamız yeterli olacaktır.

Teknik , , , , ,