¿Qué está haciendo el código fuente del módulo "this"?

192

Si abre un intérprete de Python y escribe "importar esto", como ya sabe, imprime:

El zen de Python, por Tim Peters

Hermoso es mejor que feo.
Explícito es mejor que implícito.
Simple es mejor que complejo.
Complejo es mejor que complicado.
Plano es mejor que anidado.
Escaso es mejor que denso.
La legibilidad cuenta.
Los casos especiales no son lo suficientemente especiales como para romper las reglas.
Aunque la practicidad supera la pureza.
Los errores nunca deben pasar en silencio.
A menos que sea silenciado explícitamente.
Ante la ambigüedad, rechaza la tentación de adivinar.
Debe haber una, y preferiblemente solo una, forma obvia de hacerlo.
Aunque esa manera puede no ser obvia al principio a menos que seas holandés.
Ahora es mejor que nunca.
Aunque nunca es mejor quederecho ahora.
Si la implementación es difícil de explicar, es una mala idea.
Si la implementación es fácil de explicar, puede ser una buena idea.
Los espacios de nombres son una gran idea, ¡hagamos más de eso!

En la fuente de Python (Lib / this.py) este texto es generado por un curioso fragmento 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])
bielorruso
fuente

Respuestas:

183

Esto se llama codificación rot13 :

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

Construye la tabla de traducción, tanto para caracteres en mayúscula (para esto es 65) como en minúscula (para esto es 97).

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

Imprime la cadena traducida.

Eli Bendersky
fuente
27
Y eso en realidad se puede implementar de manera más simple tanto en 2.xy 3.x como import codecs; print(codecs.decode(s, "rot-13")). Escribir el algoritmo a mano de esa manera fue solo una ofuscación adicional del huevo de pascua.
ncoghlan
12
O simplemente 'Gur Mra bs Clguba, ol Gvz Crgref'.decode('rot13').
Alex Brasetvik
3
Quizás deberíamos agregar que ROT13 fue el principal método de "encriptación" utilizado en los viejos días de usenet 8 ^)
Zane
53
@OllieFord: como una broma. Todo lo que hace el módulo, desde ofuscar el código fuente hasta implementar rot13 desde cero a pesar de que está integrado en stdlib, viola directamente el Zen de Python. Tim Peters también colocó algunas bromas sutiles en el Zen mismo (observe que los guiones en la línea TOOWTDI lo hacen de dos maneras diferentes).
abarnert 15/09
77
@abarnert Creo que el nombre del módulo thistambién forma parte de la broma porque otros lenguajes (p. ej., Java) se usan de forma thissimilar a cómo usa Python self. Escribir import thisparece tan inútil como escribir import java.self;.
Luc
25

Si desea realizar la sustitución ROT13 a mano, o en su cabeza, puede verificarlo porque 13 * 2 = 26 (el número de letras del alfabeto inglés), es esencialmente un intercambio:

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ᵀᴹ
fuente
12

Es un cifrado de sustitución, rot13 .

Michael J. Barber
fuente
11

Utiliza ROT13 codificación. Esto se usa porque es una broma.

También puede usar las funciones de Python para decodificar cadenas.

Python 2 solamente:

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

Python 2 y 3:

import codecs
print(codecs.decode(this.s, 'rot-13'))
trapwalker
fuente
Esto fue notado por los comentarios ncoghlan el 2 de mayo '11 usando import codecs. No sé si todavía se necesita importar códecs o si la disponibilidad de decodese hizo automática con alguna versión particular de Python. ¿Podría vincular a la documentación del decodeque está utilizando?
Cœur
1
@ Cœur Esto tampoco me funciona en Python 3.7 en IDLE. Tal vez esto fue Python 2?
Filip Š
@ FilipŠ oh, tienes razón, funciona con Python 2 pero no con Python 3. Pero en Python 2, puedes hacerlo import thisy lo imprimirá directamente sin ningún código adicional.
Coeur