Attributes of Python module `this`

Question:

Typing import this returns Tim Peters’ Zen of Python. But I noticed that there are 4 properties on the module:

this.i 
this.c
this.d
this.s

I can see that the statement

print(''.join(this.d.get(el, el) for el in this.s))

uses this.d to decode this.s to print the Zen.

But can someone tell me what the attributes this.i and this.c are for?

I assume they are there intentionally – answers to this question seem to suggest there are other jokes to be gleaned from the wording of the Zen. I’m wondering if there is a reference I’m missing with these 2 values.

I noticed that the values differ between Python versions:

# In v3.5:
this.c
Out[2]: 97
this.i
Out[3]: 25

# In v2.6
this.c
Out[8]: '!'
this.i
Out[9]: 25
Asked By: Noel Evans

||

Answers:

i and c are simply loop variables, used to build the d dictionary. From the module source code:

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

This builds a ROT-13 mapping; each ASCII letter (codepoints 65 through 90 for uppercase, 97 through 122 for lowercase) is mapped to another ASCII letter 13 spots along the alphabet (looping back to A and onwards). So A (ASCII point 65) is mapped to N and vice versa (as well as a mapped to n):

>>> c, i = 65, 0
>>> chr(i + c)
'A'
>>> chr((i + 13) % 26 + c)
'N'

Note that if you wanted to ROT-13 text yourself, there is a simpler method; just encode or decode with the rot13 codec:

>>> this.s
"Gur Mra bs Clguba, ol Gvz CrgrefnnOrnhgvshy 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!"
>>> import codecs
>>> codecs.decode(this.s, 'rot13')
"The Zen of Python, by Tim PetersnnBeautiful is better than ugly.nExplicit is better than implicit.nSimple is better than complex.nComplex is better than complicated.nFlat is better than nested.nSparse is better than dense.nReadability counts.nSpecial cases aren't special enough to break the rules.nAlthough practicality beats purity.nErrors should never pass silently.nUnless explicitly silenced.nIn the face of ambiguity, refuse the temptation to guess.nThere should be one-- and preferably only one --obvious way to do it.nAlthough that way may not be obvious at first unless you're Dutch.nNow is better than never.nAlthough never is often better than *right* now.nIf the implementation is hard to explain, it's a bad idea.nIf the implementation is easy to explain, it may be a good idea.nNamespaces are one honking great idea -- let's do more of those!"

As for the difference in Python 2.6 (or Python 2.7 for that matter) versus Python 3.5; the same variable name c is also used in the list comprehension in the str.join() call:

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

In Python 2, list comprehensions do not get their own scope (unlike generator expressions and dict and set comprehensions). In Python 3 they do, and the c value in the list comprehension is no longer part of the module namespace. So the last value assigned to c at the module scope is 97 in Python 3, and this.s[-1] (so a '!') in Python 2. See Why do list comprehensions write to the loop variable, but generators don't?

There is no joke embedded in these 1-letter variable names. There are jokes in the Zen itself. Like the fact that between the source code for the this module and the text itself you can find violations for just about all the rules!

Answered By: Martijn Pieters
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.