O que o código fonte do módulo "this" está fazendo?

192

Se você abrir um interpretador Python e digitar "import this", como você sabe, ele imprimirá:

O Zen de Python, de Tim Peters

Bonito é melhor que feio.
Explícito é melhor que implícito.
Simples é melhor que complexo.
Complexo é melhor que complicado.
Flat é melhor que aninhado.
Esparso é melhor que denso.
Legibilidade conta.
Casos especiais não são especiais o suficiente para violar as regras.
Embora praticidade supere a pureza.
Os erros nunca devem passar silenciosamente.
A menos que seja explicitamente silenciado.
Diante da ambiguidade, recuse a tentação de adivinhar.
Deve haver uma - e preferencialmente apenas uma - maneira óbvia de fazê-lo.
Embora esse caminho possa não ser óbvio a princípio, a menos que você seja holandês.
Agora é melhor do que nunca.
Embora nunca seja frequentemente melhor do queagora mesmo .
Se a implementação é difícil de explicar, é uma má ideia.
Se a implementação é fácil de explicar, pode ser uma boa ideia.
Os espaços para nome são uma ótima idéia - vamos fazer mais!

No código-fonte python (Lib / this.py), este texto é gerado por um curioso trecho de código:

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])
bielorrusso
fonte

Respostas:

183

Isso é chamado de codificação rot13 :

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

Cria a tabela de conversão, para caracteres maiúsculos (isto é, para 65) e minúsculos (para isso, para 97).

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

Imprime a string traduzida.

Eli Bendersky
fonte
27
E isso pode realmente ser implementado de maneira mais simples tanto em 2.x como em 3.x como import codecs; print(codecs.decode(s, "rot-13")). Escrever o algoritmo à mão dessa maneira foi apenas mais uma ofuscação do ovo da páscoa.
Ncoghlan
12
Ou apenas 'Gur Mra bs Clguba, ol Gvz Crgref'.decode('rot13').
Alex Brasetvik
3
Talvez devêssemos acrescentar que ROT13 foi o principal método de "criptografia" usadas nos velhos tempos Usenet 8 ^)
Zane
53
@OllieFord: Como uma piada. Tudo o que o módulo faz, desde ofuscar o código-fonte até implementar o rot13 do zero, mesmo estando incorporado no stdlib, viola diretamente o Zen do Python. Tim Peters também fez algumas piadas sutis no próprio Zen (observe os traços na linha TOOWTDI de duas maneiras diferentes?).
abarnert
7
@abarnert Acho que o nome do módulo thistambém faz parte da piada, porque outras linguagens (por exemplo, Java) usam thissimilar à maneira como Python usa self. Digitar import thisparece tão inútil quanto digitar import java.self;.
Luc
25

Se você deseja fazer a substituição do ROT13 manualmente - ou na sua cabeça -, pode verificar que, porque 13 * 2 = 26 (o número das letras do alfabeto inglês), é essencialmente uma troca:

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

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

Vs.

ypercubeᵀᴹ
fonte
12

É uma cifra de substituição, rot13 .

Michael J. Barber
fonte
11

Ele usa ROT13 codificação . Isso é usado porque é uma piada.

Você também pode usar funções Python para decodificar string.

Apenas Python 2:

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

Python 2 e 3:

import codecs
print(codecs.decode(this.s, 'rot-13'))
trapaceiro
fonte
Isso foi observado pelo comentário de ncoghlan em 2 de maio de 11 usando import codecs. Não sei se a importação de codecs ainda é necessária ou se a disponibilidade de decodefoi feita automaticamente com alguma versão específica do Python. Você poderia criar um link para a documentação decodeque está usando?
Cœur
1
@ Cœur Isso também não funciona para mim no Python 3.7 no IDLE. Talvez este fosse Python 2?
Filip Š
@ Filip Oh, você está certo, ele funciona com o Python 2, mas não com o Python 3. Mas no Python 2, você pode simplesmente fazer import thise imprimirá diretamente, sem nenhum código adicional.
Cœur