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

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

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.

Iterate over adjacent pairs

It's common to want to iterate over adjacent pairs of items in a list or string, i.e.

"golf" -> [('g','o'), ('o','l'), ('l','f')]


There's a few methods, and which is shortest depends on specifics.

Shift and zip

## 47 bytes
l=input()
for x,y in zip(l,l[1:]):do_stuff(x,y)


Create a list of adjacent pairs, by removing the first element and zipping the original with the result. This is most useful in a list comprehension like

sum(abs(x-y)for x,y in zip(l,l[1:]))


You can also use map with a two-input function, though note that the original list is no longer truncated.

## Python 2
map(cmp,l[:-1],l[1:])


Keep the previous

## 41 bytes, Python 3
x,*l=input()
for y in l:do_stuff(x,y);x=y


Iterate over the elements of the list, remembering the element from a previous loop. This works best with Python 3's ability to unpack to input into the initial and remaining elements.

If there's an initial value of x that serves as a null operation in do_stuff(x,y), you can iterate over the whole list.

## 39 bytes
x=''
for y in input():do_stuff(x,y);x=y


Truncate from the front

## 46 bytes
l=input()
while l[1:]:do_stuff(*l[:2]);l=l[1:]


Keep shortening the list and act on the first two elements. This works best when your operation is better-expressed on a length-two list or string than on two values.

I've written these all as loops, but they also lend to a recursive functions. You can also adjust to get cyclic pairs by putting the first element at the end of the list, or as the initial previous-value.

The Python 3.8 "walrus" assignment expressions allow a short expression to give pairs, though with an extra initial element.

>>> p=''
>>> [(p,p:=c)for c in"golf"]
[('', 'g'), ('g', 'o'), ('o', 'l'), ('l', 'f')]

• Also worth mentioning since I just used it, if you want the "initial value of x that serves as a null operation" at the end of your list as well so the final item is processed with it you can do x=''(\n)for y in*input(),x:do_stuff(x,y);x=y Jul 4, 2021 at 22:30

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+"'|'"


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.

0in instead of not all

(or, under DeMorgan's Law, any(not ...))

not all(...)
~-all(...)  # shorter than not, and with more forgiving precedence
0in(...)

not all map(f,a)
0in map(f,a)  # the reduction is more significant here because you can omit the parentheses


This only works if the falsey values in the ... sequence are actually False (or 0/0.0/etc.) (not []/""/{} etc.).

1in instead of any

This one isn't shorter with a comprehension:

any(f(x)for x in a)
1in(f(x)for x in a)


But it sometimes saves bytes with other kinds of expression by letting you omit the parentheses:

any(map(f,a))
1in map(f,a)


This has a similar truthiness-related caveat to the above, though.

Notes

These might sometimes have less favourable precedence, because they use the in operator. However, if you're combining this with a comparison you may be able to make additional use of this tip about comparison condition chaining.

You can also use these if you want the entire for-comprehension in any/all to always be fully evaluated:

any([... for x in a])
1in[... for x in a]


This one's rare, but if you need to evaluate and discard an extra expression for every item in a comprehension, you could use a dictionary here at no extra cost:

1in[(condition,side_effect)[0]for x in a]
1in{condition:side_effect for x in a}


because dict's in checks only the keys.

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.

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.

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+[1]       -> *iterable,1          (-2 bytes, 3 for tuples)
iterable+iter2     -> *iterable,*iterable2 (+1 byte, 0 for tuples, though can combine types)
[1]+iterable+[1]   -> 1,*iterable,1        (-3 bytes, -4 for tuples)
iterable+[1]+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 [1]+iterable+[1] 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[0]+s[-1]).isdigit()


With this program:

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


Some straightforward tricks that might help:

and -> *
or -> +


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


Trig without imports

You can compute cos and sin without needing to import math by using complex arithmetic. For an angle of d degrees, its cosine is

(1j**(d/90)).real


and its sine is

(1j**(d/90)).imag


Here, 1j is how Python writes the imaginary unit $$\i\$$. If your angle is r radians, you'll need to use 1j**(r/(pi/2)), using a decimal approximation of pi/2 if the challenge allows it.

If you're curious, this all works because of Euler's formula:

$$i^x = (e^{i \pi /2})^x = e^{i \pi /2 \cdot x} = \cos(\pi/2 \cdot x) + i \sin(\pi /2 \cdot x)$$

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.

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.

!= 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")


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

If you rely on data (mostly for kolmogorov-complexity problems), use the built-in zip encoding/decoding and store the data in a file (add +1 for the filename):

open('f','rb').read().decode('zip')


If you have to store the data in the source code, then you need to encode the zip with base64 and do:

"base64literal".decode('base64').decode('zip')


These don't necessarily save characters in all instances, though.

When your program needs to return a value, you might be able to use a yield, saving one character:

def a(b):yield b


However, to print it you'd need to do something like

for i in a(b):print i

• If only a single value is yielded, print next(i()) will work too. Jun 23, 2014 at 13:35
• Or just do print[*a(b)] Jun 5, 2017 at 0:59

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

Shorter isinstance

isinstance(x,C) # 15 bytes


there are several alternatives:

x.__class__==C  # 14 bytes
'a'in dir(x)    # 12 bytes, if the class has a distinguishing attribute 'a'
type(x)==C      # 10 bytes, doesn't work with old-style classes
'K'inx        # 8 bytes, only in python 2, if no other classes contain 'K'
# watch out for false positives from the hex address


Some of them may save extra bytes depending on the context, because you can eliminate a space before or after the expression.

Thanks Sp3000 for contributing a couple of tips.

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