Not easy, but clearly possible. Click on this page's title to see where this page is referenced from - there you may find some examples or discussion.
I disagree with "not easy". While Python lends itself better than many other languages to writing clear code, there's nothing magical about the language that makes it hard to write code in the style of the InternationalObfuscatedCeeCodeContest. What part of Python doesn't lend itself well to obfuscation? I assume you're going to say syntactically-significant indentation, but that's not much of a deterrent.
In fact, there are some language features that make obfuscation fun:
Sure! you have the great while..else for..else and try..else constructs! make fun with a for..else with continue or break or "raise StopIteration" and let the user guess where the control flow will appear.
Also use `foo`, and overload __nonzero__. And name "self" with another name or pass it here and there.
The fact that tab and space are both allowed only lets you make inverted-looking blocks if you can guarantee that the tab size isn't 8 for whoever's looking.
There are a number of ways in which Python's harder than C to make obscure in IOCCC fashion.
Anyone want to try their hand at some obfuscated Python? The backlinks are a good start...
Some other thoughts:
- lambda(x,y):... is different from lambda x,y: - Use nested lists [a][b][c][d][e:f] - Type tricks can be done... int,str=str,int isn't exactly subtle, though - It's probably more stylish not to obfuscate using execs/evals and lambdas - Use a string as both code (via eval/exec) and data - Take advantage of readers' knowledge of other languages: n=2 c=++n print n, c, n**c
- nested lambdas - redefine functions by assignment - make an single instance of the % operator used for both modulus and string formatting - same with +, * for addition, string concatenation, etc. - evade indentation enforcement by writing things in recursive pseudo-functional ways - do something like foo(bar(), baz()) where bar() redefines foo() and baz() - litter the code with numeric and string literals that look like they're doing something (but don't) - cause exceptions solely for the purpose of later extracting obscure data from themI don't know if this is exactly related since it's not intentionally obfuscated, but I've got a polyglot (in this case, legal C/C++, perl and Python, see also HelloPolyGlots) quine (see QuineProgram) that has some pretty unreadable Python in it. http://www.phong.org/bf/polyglotC++PerlPythonC.c
Very nice (for some interpretation of the term ;-)
# Here's an accumulator for 2.2 that has roughly a 1:6 evil:character ratio # It's not nearly at Perl or C levels, of course... class O(float):O,__new__=0,lambda O,_:O.__setattr__(O,"O",_+O.O)or O.O
See <http://www.python.org/cgi-bin/moinmoin/JustAnotherPythoneer> for various degrees of obfuscation of a simple task.
[#[#[#[#[#[#[#[#[# By TaroOgawa #]#]#]#]#]#]#]#]#] globals() .update({ "______": lambda x: globals() .update(( dict([[x] *2])))}), ______((( "Just"))) ,______(( "another" )),______ ("Python" ),______( "Hacker") ];print ( " ".join( [(Just),( (another) ),(Python ),Hacker] ));______Cute, but it doesn't actually, you know, run or anything. It does under Python 2.3+ [Hint: Make sure you copy EVERYTHING including the credit line]
Functional programming is your friend!
Here's a fully-functional, English-aware version of "99 bottles" in Python. Enjoy. Additional bonus -- it fits on one line and doesn't use any cheap indentation or variable naming tricks.
print ''.join('%(pre)s%(num)s %(bot)s on the wall, %(nul)s %(bot)s,\n%(tak)s\n' % (lambda c,b: {'pre':['','%s %s on the wall.\n\n' % (c,b)][abs(cmp(c,'Ninety-nine'))], 'num':c, 'nul':c.lower(), 'bot':b, 'tak':['Go to the store and buy some more... Ninety-nine %s.' % b,'Take one down, pass it around,'][abs(cmp(x,0))] })((lambda x,o: [(['Twenty','Thirty','Forty','Fifty', 'Sixty','Seventy','Eighty','Ninety'][x/10-2]+'-'+o.lower()).replace('-no more',''), o][int(x<20)])(x, ['No more','One','Two', 'Three','Four','Five','Six','Seven','Eight', 'Nine','Ten','Eleven','Twelve','Thirteen','Fourteen', 'Fifteen','Sixteen','Seventeen','Eighteen','Nineteen'][[x,x%10][int(x>=20)]]),'bottle%s of beer' % ['','s'][abs(cmp(x,1))]) for x in xrange(99,-1,-1))-- IvanTkatchev
That would have been so much shorter if Python had CommonLisp's FORMAT function... How so?
CommonLisp's FORMAT has number-to-word conversion built in, but only for English.
Put code in docstrings and execute the file again minus the first line, reversing the blockquotes. Example:
""" print "This is the hidden code." """ print "This is the normal code." import sys codeToExecute = '' f=open(sys.argv[0]) f.next() exec(''.join(f)) """ print "More hidden code." """ #"""Or simply
def p(n): """print 'hidden code'""" return n**2 exec(p.__doc__) # hidden code
Overwrite Fields
from __future__ import print_function; ''' print(q[1]('t9(}zw|q}/>VzrP}/q|zaJ Q>V')),exit(0)#''' q=lambda x,_=('c9*6iv"&s1[Y/`Oh7_|pEW:=!uT4+zeNl;Im\'X\\<-wabDMZ8ykgR@{r>B)~qKFdC3H0Q%,S}xVG](?^2#oPjJL.A$U fnt5'): type('').__dict__['}VJ|(@J}>'. translate(('_'*32+_+('__'*len(_))[:(1<<2)-1-(1<<8-2)]))](x,('_'*32+_+('__'* len(_))[:(1<<2)-1-(1<<8-2)]));globals()[q('11$C3qV}11')] = lambda _,q=q,__builtins__=__builtins__: __builtins__.__dict__[q('11$C3qV}11')](q(_));q2=( lambda globals=(lambda q=(lambda x: getattr(__import__('q('),x)): q): (lambda os, __import__=q: (globals()(__import__(os)))))(); q=[q2('q3>|')(__import__( '(P(').__dict__[q('JVR%')][0],0),q];q2('^93o')(3,0);raw_input();input()
Someone replaced the content of this page with a code listing. I have reverted the change, as the new content was vastly less helpful than what used to be here aside from as an overly verbose SelfDemonstratingArticle?.