This is a golf cheatsheet that lists techniques to reduce the number of chars in Python code.
n&~-n # zero for powers of 2, non-zero for others
# or
n&~-n<1
# or
n&-n-n # zero for powers of 2, non-zero for others
# or
n&-n==ninstead of
(n & (n-1) == 0) and n != 0
# or
import math;math.log(n, 2).is_integer()
# or
bin(num).count("1") == 1q**n%n # zero for powers of q, non-zero for others
# or
q**n%n<1instead of
import math;math.log(n, q).is_integer()map(chr,range(65,91))
# ABCDEFGHIJKLMNOPQRSTUVWXYZ
map(chr,range(97,123))
# abcdefghijklmnopqrstuvwxyzinstead of:
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
[chr(i+97)for i in range(26)]for i in 0,1,2:
print("fbboaaorz"[i::3])
# foo
# bar
# bazinstead of:
for i in 0,1,2:
if i == 0:
print("foo")
elif i == 1:
print("bar")
else:
print("baz")It works with strings that are the same size (+- 1 char).
For True and False, see:
print("FTarlusee"[condition::2])
# False (if condition is False)
# True (if condition is True)p<=s<p+"" # last utf-8 char
# or
p<=s<p+"~" # last printable ascii charinstead of:
s.startswith(p)NB: See the utf-8 list to see the last char.
"ATTCGAAGCCTTC".translate({65:84,84:"U"}) # "TUUCGTTGCCUUC"
"ATTCGAAGCCTTC".translate({65:84,84:"55"}) # "T5555CGTTGCC5555C"
"ATTCGAAGCCTTC".translate({65:84,84:65}) # "TAACGTTGCCAAC"instead of:
"ATTCGAAGCCTTC".replace("T","U").replace("A","T") # "TUUCGTTGCCUUC"
"ATTCGAAGCCTTC".replace("T","55").replace("A","T") # "T5555CGTTGCC5555C"
"ATTCGAAGCCTTC".replace("A","~").replace("T","A").replace("~","T") # "TAACGTTGCCAAC"Explanation: replace is costly because you have to use it once for every replacement you want to make. Moreover, when you need to exchange 2 chars ("A" -> "T" and "T" to "A"), you are forced to make one more .replace call for the exchange to give the correct result.
L=[1,3,4,8]
*_,a=L
# a = 8instead of:
L=[1,3,4,8]
a=L[-1]
# a = 8L=[1,2,3,4,5]
i=3
a=L[~i] # 2instead of
L=[1,2,3,4,5]
i=3
a=L[-i-1] # 2Explanation: ~ is the bitwise inversion, leading to ~i being equal to -i-1.
L=[1,2,3,4,5]
a=6
L+=a,instead of
L=[1,2,3,4,5]
a=6
L+=[a]
# or
L.append(a)L=[1,2,3]
M=[4,5,6]
L+=Minstead of
L=[1,2,3]
M=[4,5,6]
L.extend(M)for i in 0,1,2:instead of
for i in range(3):CAVEAT: it works only for loops of up until range(3) included.
exec("do_something;"*n)instead of
for _ in range(n):do_somethingi=n;exec("do_something;i-=1;"*n)instead of
for i in range(n,0,-1):do_somethingfor i in range(m*n):
print(i//n, i%n)instead of
for i in range(m):
for j in range(n):
print(i, j)for i in range(m*n*o):
print(i//n//o, i%(n*o)//o, i%o)instead of
for i in range(m):
for j in range(n):
for k in range(o):
print(i, j, k)s=[x,y][b]instead of:
s = y if b else xCAVEAT:
b must be True, False, 0 or 1. Being "truthy"/"untruthy" is not sufficient.
For x and y numbers and b a boolean:
| do | instead of |
|---|---|
y*b |
[0,y][b] |
y**b |
[1,y][b] |
b or x |
[x,1][b] |
x+b |
[x,x+1][b] |
x-b |
[x,x-1][b] |
x+z*b |
[x,y][b]* |
* only works if z=y-x already exists.
For x and y integers and b a boolean:
| do | instead of |
|---|---|
1|-b |
[1,-1][b] |
x^-b |
[x,~x][b] |
-x-b |
[-x,~x][b] |
L=[1,3,4,8]
M=[]
L[:1]==[1] # True
L[:1]==[2] # False
M[:1]==[1] # Falseinstead of
L=[1,3,4,8]
M=[]
next(iter(L),None)==1 # True
next(iter(L),None)==2 # False
next(iter(M),None)==1 # FalseSlicing the list is always possible, therefore [][:1] does not fail and just returns []. [][0] would fail. The interesting part is that it works when the list is empty and when the list contains at least an element with the same expression.
a=b=c=d=0
e,f=1,2instead of:
a = 0
b = 0
c = 0
d = 0
e = 1
f = 2CAVEAT: a=b=c=d=[] does not work with lists. Indeed:
a=b=c=d=[]
a.append(1)
print(a, b, c, d) # [1] [1] [1] [1]