General tips for golfing in Python

Add a reply

Posted by lifthrasiir 569 days ago:
After looking Ruby forum, I felt a need of similar thread for Python. :) As an example, the following is some general tips I know:

`x` can be used instead of str(x), if x is int (not long, because it follows with 'L')
use of bounded methods and aliases can shave some bytes, e.g. j=''.join; R=range
get rid of parentheses with bitwise operators. bitwise operators have lower precedences than arithmetic ones, so one can write 3+x>>2 instead of (3+x)/4
-~x and ~-x are equivalent to x+1 and x-1, but without (possible) parentheses.
zip(x, x[1:]) generates [(x[0], x[1]), (x[1], x[2]), ..., (x[-2], x[-1])], good for lookahead and/or lookbehind.
conditional expressions are extremely common. if you can avoid side effects, (x,y)[cond] will be a basic choice. if x=1 and cond>=0 then y**cond can be used. if both x and y are fixed strings with similar length and cond is 0 or 1 then (x[0]+y[0]+x[1]+y[1]+...)[cond::2] can be used. and so on...
bool can be treated as int, and vice versa (although some tips don't work for integer rather than 0 or 1)
some comparisons can be chained. e.g. a>1<b instead of a>1 and b>1
list.append(item) can be shortened with list += [item], or list += item,.
one can use unused variables to trigger exceptions and terminate the program. (stderr is ignored in codegolf)
as well as ruby, 0or 1 is valid python code. of course 0 or1 is not. (note that no spaces between 0 and or)

Obviously there could be more.
Posted by mick 568 days ago:
These are great tips...thanks for posting them!

I only have one more to add...if you're only using a loop variable for doing something a fixed number of times, like this:


for i in range(10):do something


You can replace it with:


exec"do something\n"*10
Posted by mick 564 days ago:
Two more tricks:

(1) If you want to put two statements on one line, separate them with ';' like this:

i+=1;j+=1

instead of

i,j=i+1,j+1

(2) If your solution needs to indent two levels deep, use a space for the first level and a tab for the second level, so that each only requires one character of indentation.
Posted by recursive 534 days ago:
If using windows, make sure your newlines aren't more than one byte, as they are by default.
Posted by Mark Byers 500 days ago:
Here are two more ways to read standard input that can sometimes be useful:

import os;x=os.read(0,99);....

import sys;for l in sys.stdin:....
Posted by danudey 487 days ago:
A few other tips I found...

The best method for user input I've found is raw_input(), which returns a string. It's a lot better than importing sys or any such things, and pretty short too.

Also, to reverse a string, try string[::-1]. Very handy.
Posted by toxik 277 days ago:
If you use raw_input more than once, it is always more efficient to alias it, r=raw_input.

The shortest way of printing out a list of strings together is print"".join(L), other ways always end up being longer.

As noted above, bools can be integers. "ab"[x>0] gives "a" if x is 0, "b" if x is above zero.

Functions with names at less than four bytes are generally not worth aliasing unless you use them *a lot.*

"%c" % (65,) is "A".

map() is very good to have.

Don't bother using semicolons, you can just use UNIX-style newlines and still maintain some code readability.

Python has very flexible tuple unpacking:

for a, (b, c) in ((1, "ab"), (2, "ba")):
....print a, b, c
1 a b
2 b a


That's about it I guess. Module imports are very rarely worth the bytes.
Posted by hallvabo 93 days ago:
Some tricks which may come in handy:

print'%i'%d saves one byte versus print int(d).

l[x+1:x-1:-1] as substitute for x[x:x+2][::-1] when x>0.

for, while and try have an optional else-clause.

To check if all elements in a sequence evaluates to True: use all(seq).
Use any(seq) to check if at least one element evaluates to True.

hex(n), oct(n) and int('...', base) is very useful when you need to encode something.

convert = lambda number, base: ''.join(str(number/i % base) for i in (..., base**3, base*base, b,1))
will convert numbers of a known upper bound to any base.

Put generator expressions inside ''.join(...) as a replacement for loops when the loop body only contains expressions.

The operator %= is overloaded for strings: s = '%c'; s%=54; print s # prints 6

int('...') works on strings of zero-padded numerals: int('009') gives 9. Useful in conjunction with string interleaving and slicing.

'#'.join('abc') gives 'a#b#c'.

'%s' converts any type or object with str(), '%r' converts with repr().

range(1e3) is shorter than range(1000). This gives a warning, but stderr is ignored in codegolf.
Posted by hendrik 32 days ago:
Related to one of lifthrasiir's tips I found out recently that you can combine bools with other types. Possibly not everybody is aware of this feature.

4+True => 5
4+False => 4
4*True => 4
4*False => 0
"ABC"*True => 'ABC'
"ABC"*False => ''

Add a reply