Co robi kod źródłowy modułu „ten”?

193

Jeśli otworzysz interpreter Pythona i wpiszesz „zaimportuj to”, jak wiadomo, wypisze:

Zen of Python, autor: Tim Peters

Piękne jest lepsze niż brzydkie.
Jawne jest lepsze niż niejawne.
Prosty jest lepszy niż złożony.
Złożony jest lepszy niż skomplikowany.
Mieszkanie jest lepsze niż zagnieżdżone.
Rzadki jest lepszy niż gęsty.
Liczy się czytelność.
Przypadki specjalne nie są wystarczająco wyjątkowe, aby złamać zasady.
Chociaż praktyczność przewyższa czystość.
Błędy nigdy nie powinny przejść bezgłośnie.
Chyba że wyraźnie uciszony.
W obliczu dwuznaczności odmów pokusy zgadywania.
Powinien być jeden - a najlepiej tylko jeden - oczywisty sposób na zrobienie tego.
Chociaż na początku taki sposób może nie być oczywisty, chyba że jesteś Holendrem.
Teraz jest lepiej niż nigdy.
Chociaż nigdy nie jest często lepszy niżwłaśnie teraz.
Jeśli implementacja jest trudna do wyjaśnienia, to zły pomysł.
Jeśli implementacja jest łatwa do wyjaśnienia, może to być dobry pomysł.
Przestrzenie nazw to jeden świetny pomysł - zróbmy więcej z nich!

W źródle Pythona (Lib / this.py) ten tekst jest generowany przez ciekawy fragment kodu:

s = """Gur Mra bs Clguba, ol Gvz Crgref

Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""

d = {}
for c in (65, 97):
    for i in range(26):
        d[chr(i+c)] = chr((i+13) % 26 + c)

print "".join([d.get(c, c) for c in s])
białoruski
źródło

Odpowiedzi:

184

Nazywa się to kodowaniem rot13 :

d = {}
for c in (65, 97):
    for i in range(26):
        d[chr(i+c)] = chr((i+13) % 26 + c)

Tworzy tabelę tłumaczeń, zarówno dla wielkich liter (to jest 65), jak i małych (to jest 97) znaków.

print "".join([d.get(c, c) for c in s])

Drukuje przetłumaczony ciąg.

Eli Bendersky
źródło
27
I to może być faktycznie zaimplementowane prościej zarówno w wersji 2.x, jak i 3.x as import codecs; print(codecs.decode(s, "rot-13")). Ręczne napisanie algorytmu było tylko dalszym zaciemnieniem pisanki.
ncoghlan
12
Lub po prostu 'Gur Mra bs Clguba, ol Gvz Crgref'.decode('rot13').
Alex Brasetvik
3
Może powinniśmy dodać, że ROT13 był główną metodą „szyfrowania” używaną w dawnych czasach usenetu 8 ^)
Zane
53
@OllieFord: Jako żart. Wszystko, co robi moduł, od zaciemniania kodu źródłowego do implementacji rot13 od zera, nawet jeśli jest wbudowane w stdlib, bezpośrednio narusza Zen Pythona. Tim Peters również wrzucił kilka subtelnych żartów do samego Zen (zauważ, że kreski na linii TOOWTDI robią to na dwa różne sposoby?).
abarnert
7
@abarnert Myślę, że nazwa modułu, thisjest również częścią żartu, ponieważ inne języki (np. Java) używają thispodobnie jak Python self. Pisanie import thiswydaje się tak samo bezcelowe jak pisanie import java.self;.
Luc
25

Jeśli chcesz dokonać podstawienia ROT13 ręcznie - lub w głowie - możesz to sprawdzić, ponieważ 13 * 2 = 26 (liczba liter alfabetu angielskiego), jest to w zasadzie zamiana:

a <-> n
b <-> o
c <-> p
...
m <-> z

A <-> N
B <-> O
C <-> P
...
M <-> Z 

Vs lbh cenpgvfr ybat rabhtu, lbh'yy riraghnyyl znfgre gur Mra bs EBG-13 nytbevguz naq ernq guvf Xyvatba ybbxvat grkgf jvgubhg pbzchgre uryc.

ypercubeᵀᴹ
źródło
11

Wykorzystuje kodowanie ROT13 . Jest to używane, ponieważ jest to żart.

Możesz także użyć funkcji Pythona do odkodowania łańcucha.

Tylko Python 2:

import this
print(this.s.decode('rot13'))

Python 2 i 3:

import codecs
print(codecs.decode(this.s, 'rot-13'))
trapwalker
źródło
Zostało to zauważone przez komentarz ncoghlan z 2 maja 11 przy użyciu import codecs. Nie wiem, czy importowanie koderów-dekoderów jest nadal potrzebne, czy też dostępność decodejest automatyczna w niektórych wersjach Pythona. Czy możesz połączyć się z dokumentacją decode, której używasz?
Cœur
1
@ Cœur To również nie działa w Pythonie 3.7 w IDLE. Może to był Python 2?
Filip Š
@ FilipŠ och, masz rację, działa z Python 2, ale nie z Python 3. Ale w Python 2 możesz to zrobić import thisi wydrukuje go bezpośrednio, bez dodatkowego kodu.
Cœur