# Tips for golfing in Python

What general tips do you have for golfing in Python? I'm looking for ideas which can be applied to code-golf problems and which are also at least somewhat specific to Python (e.g. "remove comments" is not an answer).

• Use Python 2 for golfing not 3 Aug 9, 2017 at 15:04
• @Chris_Rands That simply does not universally hold, as there are cases in which Python 3 allows for shorter submissions. Jul 15, 2018 at 14:36
• @JonathanFrech Especially the new := operator in 3.8 Mar 17, 2019 at 17:31
• Feb 2, 2021 at 11:54

## Multiple if statements in comprehensions

If you need to keep multiple conditions inside comprehension, you can replace and with if to save a byte each time.

Works in Python 2 and 3.

[a for a in 'abc'if cond1()and cond2()or cond3()and cond4()and cond5()]
[a for a in 'abc'if cond1()if cond2()or cond3()if cond4()if cond5()]


Try it online!

Be aware of all, any and map:

if isdigit(a) and isdigit(b) and isdigit(c)
if all(map(isdigit,[a,b,c]))

• filter(function, iterable) returns a list of all the elements of iterable for which function is a True-y value and a non-empty list is True-y, so this can be shortened further to if filter(isdigit,[a,b,c]) Apr 16, 2014 at 8:33
• Over a year later, I'm reading this thread again and I'm embarrassed about my previous comment. if filter(isdigit,[a,b,c]) is not equivalent to the code in the answer; but it would be if @moose used isdigit(a) or... and if any(.... Apr 21, 2015 at 13:36

Sometimes you need convert boolean expression into integer (0/1) Simple use this Boolean (in examples below c > 0) in ariphmetic

a=b+(c>0)
a+=c>0
a=sum(c>0 for c in b) # space in "0 for" may be omitted


And sometimes you need simple convert boolean to int (for example for printing or convert to binary string). In programm you may use some variants

1 if c>0 else 0
c>0and 1or 0
(0,1)[c>0]
int(c>0)


but shortest way is

+(c>0)

• I find +c being shorter. E.g. let c be a boolean, then 4+c is 5 if c is True else 4. Feb 25, 2014 at 23:41

# Take multi-line input

Use list(iter(input,eof)) to take multi-line input. eof can be any string that you want to stop taking input on if you see it. An example would be eof = ''. The python 2 version is list(iter(raw_input,eof)), however you may want to use sys.stdin.readlines() instead if you have already imported sys.

• list(iter(input,eof)) is shorter by one, you don't need that space. Also worth noting that this is only for Python 3 - Python 2 is 4 bytes longer because raw_input.
– user45941
Nov 30, 2015 at 3:15
• Is shorter than what? Nov 30, 2015 at 3:33
• Than what you have posted, because it has an extraneous space.
– user45941
Nov 30, 2015 at 3:34
• Oh, I see. I assume the reader would remove the space though. I will edit it out now. Nov 30, 2015 at 3:38
• read(0) returns an iterable of all lines of input on many systems (in Python 3.9, not sure when it was added). May 16, 2021 at 19:24

# Use slicing + assignment instead of mutator methods

l.insert(x,y) # before
l[x:x]=y,     # after

l.reverse()   # before
l[::-1]=l     # after

l.append(x)   # before
l[L:]=x,      # after (where L is any integer >= len(l))

l[:]=x        # set the contents of l to the contents of x


EDIT: thanks to @quintopia for pointing this out, these are statements, not expressions. The mutator methods are void functions, so they are expressions which evaluate to None. This means that things like [l.reverse() for x in L] and condition or l.reverse() are valid, whereas [l[::-1]=l for x in L] and condition or l[::-1]=l are not.

• Note that this cannot always be done. For instance, when using or or and as conditionals, assignment is not allowed, but append and the like are. Jan 13, 2016 at 5:34
• l[:]=x is a bit unpythonic - same number of bytes, but I reckon l=x[:] is better practice. Also, [::-1] is listed as a tip here, L[:x]+=y, is better for the general case where x might be an expression (but same byte count if it's just x), and l+=x, is listed here for append. Feb 17, 2016 at 7:10
• @Sp3000 l[:]=x and l=x[:] do different things. The former mutates the list itself, i.e. all references to that list, whereas the latter sets the variable l to a copy of x Feb 17, 2016 at 7:47
• @Cyoce Oh, nevermind then - my eyes are going to have to get used to seeing that :P Feb 17, 2016 at 8:01
• l+=[x] is shorter than l[L:]=x, Jun 28 at 14:19

## Find the n'th number meeting a condition

Many sequence challenges ask you to find the n'th number in a sequence of increasing positive integers. When you have a expression p(i) that checks membership, you can do this with the recursive function:

f=lambda n,i=1:n and-~f(n-p(i),i+1)


Note that expression p(i) must give 0 or 1, not just Falsey or Truthy. The outputs are one-indexed, so say for the sequence of primes, it would give

f(1) = 2
f(2) = 3
...


For 0-indexed outputs, shift the base case

f=lambda n,i=1:n+1and-~f(n-p(i),i+1)


The recursive function f=lambda n,i=1:n and-~f(n-p(i),i+1) works by decrementing the required count n each time it gets a hit, and incrementing the output value each time for each value it checks. It might seem weird to redundantly track i, but it's longer to do:

f=lambda n,i=1:n and f(n-p(i),i+1)or~-i


Also compare the natural list strategy (zero-indexed here)

lambda n:[i for i in range(n*n)if p(i)][n]


(You might need a larger bound than n*n.)

Format() works on dates:

"We are in year: %s" % (date.strftime('%y'))


Becomes:

"We are in year: {:%y}".format(date)


Or even better with f-strings:

f"We are in year: {date:%y}"


# Formatting a Matrix

I've seen this code to get a character matrix (2D array) as a string.

'\n'.join(''.join(i)for i in M)


It's shorter to use a map instead:

'\n'.join(map(''.join,M))


If you're printing the result, it's shortest to use a for loop:

print('\n'.join(map(''.join,M)))
for i in M:print(*i,sep='')      # -5 bytes


If you're using Python 2, you can't use the print trick, but you can still use the for loop:

for i in M:print(''.join(i))     # -3 bytes


In Python,

True == 1   # true
False == 0  # true


So,

(a<b)*2-1


returns 1 if b is larger than a. If not, returns -1.

More golfing,

-(a>b)|1


returns exactly same value as mentioned above.

Useful when modify iterator index by comparable values.

• a<b or-1 also works Oct 17, 2021 at 18:00

## Math built-ins in 3.8

In addition to the famous walrus operator, Python 3.8 introduces useful new math features.

Modular inverse

The modular-power built-in pow(base, exp, mod) can now compute the modular inverse using exp=-1. This requires that base and mod are relatively prime integers.

>>> pow(38, -1, 97)
23
>>> 23 * 38 % 97 == 1
True


exp may be any negative integer, which lets you compute modular powers of the modular inverse.

The math library has useful new functions for combinatorics and distances. Access them with import math. Or, write from math import* to import them without the math., which is worth it if you write more than one call.

Combinatorics

• math.comb(n,k): The binomial coefficient n choose k, which equals n! / (k! * (n - k)!).
• math.perm(n,k): The number of ordered choices of k elements from n, which is n! / (n - k)!. Calling just math.perm(n) gives n!, useful as a synonym for math.factorial(n).
• math.prod(l): The product of the elements of a list or iterable l, analogous to sum.

Distances and square roots

• math.dist(p,q): The Euclidean distance between two points p and q. The inputs p and q must be lists or iterables that are the same length.
• math.hypot(*p): The Euclidean distance from a point p to zero. Now takes any number of arguments; before it took only two. For some reason, arguments still must be splatted like math.hypot(1,2,3) rather than math.hypot([1,2,3]).
• math.isqrt(n): The integer square root, that is the floor of the square root of n. Requires than n is a non-negative integer. Usually n**.5//1 suffices instead, but this gives exact integer output rather than a float.

# Using exec to remove repeated print

This is not quite often applicable, but can save some bytes, especially in ASCII art. Take the following code, which prints the flag where n=4.

# 43 bytes                  |  ***
n=input()                   |  **
while~-n:n-=1;print'*'*n    |  *
print'|'                    |  |


Notice that we repeat print twice. We can remove this using exec in the following code, saving 3 bytes.

# 40 bytes
n=input()
exec"'*'*n;n-=1;print"*n+"'|'"


# Printing the elements of a list, with spaces

Suppose we have to print a list as a string with spaces, like square of numbers upto 10. Then,

print(' '.join(str(i**2)for i in range(11))) # 44 chars

print(*(i**2for i in range(11))) # 32 chars


# Shorten while 1

It is possible to shorten a while 1: by replacing the 1 with an existing expression inside of the loop body. Common ways to make use of this in Python 3 include embedding

• a print() statement:
while 1:print(x);...
# vs
while[print(x)]:...

• a chained expression:
while 1:x>1==print(x);...
# vs
while[x>1==print(x)]:...

• a walrus operator (Python 3.8 and above):
while 1:x=1;...
while x:=1:...


In general, any expression (one that returns a value), can be used as the while condition to save a byte or two. Often it's necessary to wrap the expression in [] to ensure it maintains a truthy value.

## Special characters in string literals

When you write a quoted literal string in your code, perhaps to compress a big blob of data, certain characters must be replaced by a two-character escape sequence.

Null byte \0 (ASCII 0)

The null byte can't be present verbatim in Python code. Write it as \0.

Newline \n (ASCII 10)

An actual newline \n can't appear in a string literal because the Python lexer will read it and think the line has ended without closing the initial quote. But, a triple-quoted string like '''stuff''' or """stuff""" may contain newlines. This saves bytes with 5+ newlines, which can be useful in ASCII art.

Carriage return \r (ASCII 13)

A carriage return always needs escaping as \r. Though allowed in a triple-quoted string, a literal \r is misread as a newline \n.

Quotes " (ASCII 34) and ' (ASCII 39)

A single-quoted string can contain double quotes like '"', but must escape single-quotes like '\'', and vice-versa for double-quoted strings. Choose whichever option leads to less escaping.

A triple-quoted string is OK with unescaped quotes of the same type like '''it's'''. But, having quotes at the start and end or three-in-a-row can confuse the lexer into giving a SyntaxError.

Backslash \ (ASCII 92)

A backslash can be escaped as \\. But, Python allows just writing \ if it's followed by a character that can't make it an escape sequence. This is any character not in abfnrtvx0123456789"'\ or literal newline \n.

You can use a r-prefixed raw string like r'\n' to ignore most escape sequences, so r'\n' is just a backslash followed by a letter n and r'\\' is two backslashes. Quote characters still get escaped but don't consume the backslash, so r'\'' is backslash then single-quote. This can cause complications: r'\', r'\\\', and r'\\'' all give SyntaxError.

For reference, the special characters are ASCII values [0, 10, 13, 39, 34, 92]. When doing compression, you might tweak your method to avoid hitting these values.

Some weird characters can be written verbatim without escaping, such as:

• bell \a (ASCII 7)
• backspace \b (ASCII 8)
• tab \t (ASCII 9)
• vertical tab (ASCII 11)
• form feed \f (ASCII 12)
• DEL (ASCII 127)

StackExchange posts won't render these, but Python clients and TIO should handle them fine. Here they are for copy-pasting.

Characters with ASCII codes 128 and up can't be included in Python 2 code without a extra line declaring an encoding like this. Python 3, though, handles them fine, including multibyte Unicode characters.

!= can be replaced with -
here is a example

n=int(input())
if n!=69:
print("thanks for being mature")


instead of using != you can use -
after that it should look like this

n=int(input())
if n-69:
print("thanks for being mature")


## Use the walrus operator := in list comprehension to store the previous value of the iterable

Instead of the convoluted

f=[s[i]for i in range(len(s))if s[i-1]!=s[i]]


You can use

e=""
f=[c for c in s if e!=(e:=c)]


Which saves 11 bytes in this example. Care needs to be taken that e is reassigned after being evaluted. It also needs to be initialised before the list, which is quite easy to do with default function arguments

If you need to import a lot of modules you can reassign __import__ to something shorter, this also has the advantage of being able to name imports anything you want.

i=__import__;s=i('string');x=i('itertools');

• I've rarely found this to be actually useful. Generally import string,itertools, import string,itertools as M, from itertools import* and other variants tend to be shorter... Jul 25, 2015 at 9:05
• s,i=map(__import__,['string','itertools']) is shorter than your example, but still longer than import string as s,itertools as i Jul 12, 2017 at 14:44

Abusing try/except blocks can sometimes save characters, especially for exiting out of nested loops or list comprehensions. This:

for c in s:
for i in l:
q=ord(c)==i
if q:print i,c;break
if q:break


... can become this, saving 3 characters:

try:
for c in s:
for i in l:
if ord(c)==i:print i,c;1/0
except:0


... which in this particular instance can be compressed even further using list comprehensions:

try:[1/(ord(c)-i)for c in s for i in l]
except:print i,c


For an example, see e.g. https://codegolf.stackexchange.com/a/36492/16766.

When using Python 3, for your final print statement, use exit to save one char (note: this prints to STDERR, so you might not be able to use this):

print('x')
exit('x')


exit even adds a trailing newline. There is one caveat, however: exit(some_integer) will not print.

• Does this print to STDOUT or STDERR? This sounds like it would be the latter, but in most challenges only the former is allowed. Apr 19, 2015 at 4:24
• @Sp3000 I don't know... how can I tell? Apr 19, 2015 at 5:18
• Seems to be stderr Apr 19, 2015 at 5:32
• exit(some_integer) is valid because exit code is a default output form. Jun 23, 2020 at 15:20

# Alternatives to builtin string functions

### str.capitalize for single words

Use str.title instead for single words. The difference between the two functions is that capitalize only capitalises the first word, while title capitalises all words:

>>> "the quick brown fox".capitalize()
'The quick brown fox'
>>> "the quick brown fox".title()
'The Quick Brown Fox'


### str.index

str.find is almost always better, and even returns -1 if the substring is not present rather than throwing an exception.

### str.startswith

See this tip by @xnor.

### str.splitlines

str.split is shorter:

s.splitlines()
s.split('\n')


However, str.splitlines may be useful if you need to preserve trailing newlines, which can be done by passing 1 as the keepends argument.

## Avoid the repeat argument of itertools.product

As @T.Verron points out, in most cases (e.g. ranges and lists), you can instead do

product(*[x]*n)


However, even if you have a generator which you can only use once, like a Python 3 map, the repeat argument is still unnecessary. In such a case you can use itertools.tee:

product(x,repeat=n)
product(*tee(x,n))


For n = 2 you don't even need to include n, since 2 is the default argument to tee.

• product(*[L]*n) is even shorter. Oct 8, 2015 at 11:59
• @T.Verron The initial use case I had in mind was something like a Python 3 map, for which that wouldn't work, but I'll add it as a note thanks :) Oct 8, 2015 at 12:05
• Doesn't feersum have an open 500-point bounty for using itertools at all in a sufficiently old question? Oct 8, 2015 at 13:17

## Dictionary defaults as entries

Say you have an dictionary literal, which I'll denote {...}, and you want to get the value for a key k, with a default of d if k is missing.

You can save two bytes by prepending an entry rather than using get

{k:d,...}[k]
{...}.get(k,d)


Because later entries override earlier ones of the same key, the entry k:d gets overwritten if it appears in the dict, but remains if key k isn't present.

Note that this required writing k twice, which is fine for a variable, but poor when k is an expression.

If transforming from list to a tuple or set to a set, list or tuple is needed, as of Python 3.5 you can use the splat operator:

tuple(iterable) -> (*iterable,)  (-3 bytes)
set(iterable)   -> {*iterable}   (-2 bytes)
list(iterable)  -> [*iterable]   (-3 bytes)


If you're doing this as well as appending/prepending, you can do the following for an extra bonus:

iterable+       -> *iterable,1          (-2 bytes, 3 for tuples)
iterable+iter2     -> *iterable,*iterable2 (+1 byte, 0 for tuples, though can combine types)
+iterable+   -> 1,*iterable,1        (-3 bytes, -4 for tuples)
iterable++iter2 -> *iterable,1,*iter2   (0 bytes, -1 for tuples)


Basically, ,* instead of , gives a +1 byte penalty and , instead of ,[] gives -2 bytes.

This shows [1,*iterable,1] is a golfier way of doing +iterable+ by one byte, even when we're not doing any type conversion.

And just for fun, {*{}} is the same length as set() for challenges without letters.

• The last one can also be useful if there is a letter preceding set() (e.g. ...and set() can become ...and{*{}}). Oh, and it can be replaced with {*()} or {*[]} if an empty dict feels unsettling. ;-) Jun 29, 2018 at 22:37

## Difference of two parallel expressions

Say you have a challenge to find the difference of some characteristic on two inputs. Your solution has the form lambda a,b:e(b)-e(a), where e is some long expression you've written. Repeating e twice is wasteful, so what do you do?

Here are templates sorted by length. Assume that e stands for a long expression, not one that's already defined as a function. Also assume inputs can be taken in either order.

31 bytes*

lambda*l:eval('e(%s)-'*2%l+'0')


*Requires that e only mentions its variable once. Assumes -e(x) negates the whole expression, otherwise requires parens like -(e(x)) for two more bytes.

34 bytes

f=lambda a,*b:e(a)-(b>()and f(*b))


36 bytes

lambda a,b:d(b)-d(a)
d=lambda x:e(x)


36 bytes

a,b=[e(x)for x in input()]
print b-a


37 bytes

r=0
for x in input():r=e(x)-r
print r


39 bytes

lambda*l:int.__sub__(*[e(x)for x in l])


# Shorter way to copy/clone a list

(not deep clone. For deep clone see this answer)

(credit to this answer)

a=x[:]
b=[*x]
c=x*1


Try it online!

• Alternative in Python 3 which can be shorter when combined with other assignments: *d,=x Jan 2 at 0:58

## Replace not with 1-

In python, the negation operator not wastes bytes, so we have to find a shorter way. Negation can be implemented as subtraction from 1 (obtained from my Keg experiece), which saves 1 byte. (Also, True and False can be alternatively represented as 1 and 0 internally, so this will not matter much.)

Compare this program:

lambda s:not(s+s[-1]).isdigit()


With this program:

lambda s:1-(s+s[-1]).isdigit()


Some straightforward tricks that might help:

and -> *
or -> +


# dict.get as a first-class function

# all keys in the dict G with a truthy value
[k for k in G if G[k]]
filter(G.get,G)

# all keys in the dict G with a falsy value
[k for k in G if not G[k]]
G.keys()-filter(G.get,G)


# {…,**d} or a|b to merge dicts in Python

# merge two dicts
a={…}
b={…}
# Python <3.9
merged={**a,**b} # the order lets you decide which overrides which
# Python ≥3.9
merged=a|b

# set a defaut value
G.setdefault(a,1)
G[a]=G.get(a,1)
# Python <3.9
G={a:1,**G}
# Python ≥3.9
G={a:1}|G


# Extract elements from a list using ::

# This is a very specific tip when you want to get both an element at
# the near beginning of a list and one somewhere near the end.
# For example, let's assume you want to take the elements at indices i=6 and j=37
# from a list L of length l=40 (it works only if i+j*2<l)

# ok
a=L;b=L
# equivalent
a,b=L,L
# 36 = 5 + 31
a,b=L[5::31]


# Set literals

set() is 5 chars just to create an empty set. If you can have an initial element e, you can save 2 chars with {e}.

# Generators instead of comprehension lists in function calls

# assuming the function iterates on its argument
f([x**2 for x in range(4)])
f(x**2 for x in range(4))


# Access static methods on instances

If you're accessing a static method or class method, for example int.from_bytes or dict.fromkeys, you can also still access them on instances of that class - it doesn't have to be on the class itself. It's very often shorter to do this:

int.from_bytes(...
0 .from_bytes(...

dict.fromkeys(...
{}.fromkeys(...


Often you already have an instance of that class stored in a one-letter variable, so it can be even shorter:

x.from_bytes


It doesn't matter what value x is, and it isn't changed.

Sometimes you can use Python's exec-statement combined with string repetition, to shorten loops. Unfortunately, you can't often use this, but when you can you can get rid of a lot of long loop constructs. Additionally, because exec is a statement you can't use it in lambdas, but eval() might work (but eval() is quite restricted in what you can do with it) although it's 2 characters longer.

Here is an example of this technique in use: GCJ 2010 1B-A Codegolf Python Solution

• What kind of restrictions are you thinking about? I don't think Python in itself has any kind of restriction on exec, so you must be referring to problem statements? Jan 28, 2011 at 8:43
• @hallvabo, you're right it's eval() I was most likely thinking of. You can't do eval("print 1") because print 1 is a statement. I'll update the post. Jan 28, 2011 at 10:23
• As a general rule, this is worth trying when you need to do something n times, but don't care about the index. As soon as you need to initialise a loop variable and increment it, it ends up slightly longer than a for loop Feb 3, 2011 at 20:35
• In Python 3 you can do eval("print(1)") since print() is now a function. Apr 20, 2014 at 23:02
• In Python 3 you can also do exec("print(1)") since exec() is now a function. May 28, 2017 at 5:37

Was somewhat mentioned but I want to expand:

[a,b],[c,d]=[[1,2],[3,4]]


works as well as simple a,b=[1,2]. Another great thing is to use ternary operator (similiar to C-like ?:)

x if x<3 else y


and no one mentioned map. Map will call first function given as first argument on each item from second argument. For example assume that a is a list of strings of integers (from user input for example):

sum(map(int,a))


will make sum of all integers.

• Quoting the OP: Please post one tip per answer. Jun 23, 2014 at 13:53
• x if cond else y == cond and x or y`. Jul 5, 2018 at 9:34