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).

Please post one tip per answer.

  • 23
    Oh, I can see a whole set of questions like this one coming for each language... – R. Martinho Fernandes Jan 28 '11 at 4:26
  • 4
    @Marthinho I agree. Just started a C++ equivalent. I don't think its a bad thing though, as long as we don't see the same answers re-posted across many of these question types. – marcog Jan 28 '11 at 12:28
  • 44
    Love the question but I have to keep telling myself "this is ONLY for fun NOT for production code" – Greg Guida Dec 21 '11 at 0:08
  • 2
    Shouldn't this question be a community wiki post? – dorukayhan May 29 '16 at 15:35
  • 2
    @dorukayhan Nope; it's a valid code-golf tips question, asking for tips on shortening python code for CG'ing purposes. Such questions are perfectly valid for the site, and none of these tags explicitly says that the question should be CW'd, unlike SO, which required CG challenges to be CW'd. Also, writing a good answer, and finding such tips always deserves something, that is taken away if the question is community wiki (rep). – Erik the Outgolfer Sep 9 '16 at 14:48

133 Answers 133

Use a=b=c=0 instead of a,b,c=0,0,0.

Use a,b,c='123' instead of a,b,c='1','2','3'.

  • 1
    that's nice tip in general :) – user18660 Mar 20 '14 at 20:11
  • 22
    Note that this will not necessarily work for defining mutable objects that you will be modifying in-place. a=b=[1] is actually different from a=[1];b=[1] – isaacg Apr 23 '14 at 9:02
  • 6
    The funny thing about the first tip is that it works in Java too. – Justin Apr 24 '14 at 7:46
  • 1
    @Justin Yes, but only with primitive types – HyperNeutrino Sep 12 '15 at 15:41
  • 4
    But NEVER use a=b=c=[] or any object instanciation since all the variables will point to the same instance. That's probably not what you want. – PhE Aug 22 '17 at 13:38

Conditionals can be lengthy. In some cases, you can replace a simple conditional with (a,b)[condition]. If condition is true, then b is returned.

Compare

if a<b:return a
else:return b

To this

return(b,a)[a<b]
  • 34
    These aren't exactly the same. The first one evaluates only the expression that is returned while the second one always evaluates them both. These ones do short-circuit: a if a<b else b and a<b and a or b – marinus May 3 '11 at 11:34
  • 3
    (lambda(): b, lambda(): a)[a < b]() make your own short-circuit with lambdas – Ming-Tang May 7 '11 at 23:33
  • 3
    @marinus, they are not equal: just consider P and A or B for any A that gives bool(A)=False. But (P and [A] or [B])[0] will do the job. See diveintopython.net/power_of_introspection/and_or.html for reference. – kgadek Apr 24 '13 at 11:01
  • 6
    Lambdas are way longer than a conditional expression. – user2357112 Mar 20 '14 at 7:07
  • 16
    @user2357112 But they make you look so much cooler when you use them. :] – Chase Ries Mar 20 '14 at 9:06

A great thing I did once is:

if 3 > a > 1 < b < 5: foo()

instead of:

if a > 1 and b > 1 and 3 > a and 5 > b: foo()

Python’s comparison operators rock.


Using that everything is comparable in Python 2, you can also avoid the and operator this way. For example, if a, b, c and d are integers,

if a<b and c>d:foo()

can be shortened by one character to:

if a<b<[]>c>d:foo()

This uses that every list is larger than any integer.

If c and d are lists, this gets even better:

if a<b<c>d:foo()
  • 18
    Of course if this were actually golfed it'd be 3>a>1<b<5 – Rafe Kettler Jan 28 '11 at 0:35
  • 4
    Love the symmetry. Reminds me of the old Perl golf trick for finding the min of $a and $b: [$a => $b]->[$b <= $a] :) – Simon Whitaker Feb 3 '11 at 21:42
  • Note that the second example (no lists) can also be done with if(a<b)+(c>d):foo() – WorldSEnder May 22 '14 at 10:39
  • 6
    The + should be a *. An or would be + – WorldSEnder May 22 '14 at 10:53
  • Perl 6 allows it too – malkaroee Sep 28 '14 at 22:08

If you're using a built-in function repeatedly, it might be more space-efficient to give it a new name, if using different arguments:

r=range
for x in r(10):
 for y in r(100):print x,y
  • 5
    Didn't actually save any bytes, though. – user2357112 Mar 20 '14 at 7:06
  • 1
    r=range and the other two r's are 9 characters; using range twice is 10 characters. Not a huge saving in this example but all it would take is one more use of range to see a significant saving. – Frank Aug 25 '16 at 19:52
  • 8
    @Frank The additional newline is another character. – L3viathan Nov 14 '16 at 20:45
  • 1
    Indeed two repetitions is too little to save on a length five function name. You need: length 2: 6 reps, length 3: 4 reps, length 4 or 5: 3 reps, length >=6: 2 reps. AKA (length-1)*(reps-1)>4. – Ørjan Johansen Mar 18 '17 at 16:26

Sometimes your Python code requires you to have 2 levels of indentation. The obvious thing to do is use one and two spaces for each indentation level.

However, Python 2 considers the tab and space characters to be different indenting levels.

This means the first indentation level can be one space and the second can be one tab character.

For example:

if 1:
 if 1:
\tpass

Where \t is the tab character.

  • Cool, I never thought about this one! – Jules Olléon Jun 24 '11 at 19:09
  • 85
    This fails in python3: you can no more mix spaces and tabs(a bad thing for codegolf, but a good thing in all other cases). – Bakuriu Oct 19 '13 at 15:41
  • In python 3.4 this seems to work fine. – trichoplax Aug 15 '16 at 23:09
  • 2
    @trichoplax, In python 3.4.3 I get TabError: inconsistent use of tabs and spaces in indentation. – ceilingcat Oct 3 '16 at 5:16
  • For reference, a tab is worth 8 spaces. – Erik the Outgolfer Jun 29 at 22:35

Use string substitution and exec to deal with long keywords like lambda that are repeated often in your code.

a=lambda b:lambda c:lambda d:lambda e:lambda f:0   # 48 bytes  (plain)
exec"a=`b:`c:`d:`e:`f:0".replace('`','lambda ')    # 47 bytes  (replace)
exec"a=%sb:%sc:%sd:%se:%sf:0"%(('lambda ',)*5)     # 46 bytes  (%)

The target string is very often 'lambda ', which is 7 bytes long. Suppose your code snippet contains n occurences of 'lambda ', and is s bytes long. Then:

  • The plain option is s bytes long.
  • The replace option is s - 6n + 29 bytes long.
  • The % option is s - 5n + 22 + len(str(n)) bytes long.

From a plot of bytes saved over plain for these three options, we can see that:

  • For n < 5 lambdas, you're better off not doing anything fancy at all.
  • For n = 5, writing exec"..."%(('lambda ',)*5) saves 2 bytes, and is your best option.
  • For n > 5, writing exec"...".replace('`','lambda ') is your best option.

For other cases, you can index the table below:

          1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 (occurences)
       +---------------------------------------------------------
     3 |  -  -  -  -  -  -  -  -  -  -  -  -  -  -  r  r  r  r  r  
     4 |  -  -  -  -  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  
     5 |  -  -  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  r  r  
     6 |  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     7 |  -  -  -  -  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     8 |  -  -  -  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     9 |  -  -  -  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    10 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    11 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    12 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r = replace
    13 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   % = string %
    14 |  -  %  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   - = do nothing
    15 |  -  %  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
  (length)

For example, if the string lambda x,y: (length 11) occurs 3 times in your code, you're better off writing exec"..."%(('lambda x,y:',)*3).

  • 3
    this should get more votes, it's a very useful tip. – bigblind May 11 '13 at 0:18
  • 6
    it's extremely rare that this works. the cost of replace is huge. – boothby Oct 27 '13 at 2:09
  • 3
    When it does work, though, it helps a lot. – undergroundmonorail Apr 16 '14 at 8:28
  • Interesting, never even tghought of this! – Claudiu Sep 25 '14 at 22:23
  • I added a new operator for lambda in my language based off of python: => is just the string = lambda . For example, f=>:0 would be f = lambda: 0. – NoOneIsHere Mar 10 '16 at 16:18

Use extended slicing to select one string from many

>>> for x in 0,1,2:print"fbboaaorz"[x::3]
... 
foo
bar
baz

vs

>>> for x in 0,1,2:print["foo","bar","baz"][x]
... 
foo
bar
baz

In this Boolean two-string case, one can also write

b*"string"or"other_string"

for

["other_string","string"][b]

Unlike interleaving, this works for strings of any length, but can have operator precedence issues if b is instead an expression.

  • Note that the first example is exactly the same length as for x in ("foo","bar","baz"): print x – Mateen Ulhaq Jun 2 '17 at 7:21
  • 1
    @MateenUlhaq, That's just an example of how the different values of x are rendered. The golfed part is the "fbboaaorz"[x::3] vs ["foo","bar","baz"][x] How the x value is derived would be another part of your golf solution. – gnibbler Jun 2 '17 at 7:31

Use `n` to convert an integer to a string instead of using str(n):

>>> n=123
>>> `n`
'123'
  • 32
    Nice, but doesn't work with Python3. – Alexandru Jan 28 '11 at 0:04
  • 1
    Attention: really works for integers, but not for strings, for example. – Nakilon Jan 28 '11 at 0:12
  • 39
    btw. `` is short for repr – Alexandru Jan 28 '11 at 2:14
  • 9
    Integers smaller than -2**31 or bigger than 2**31-1 (Longs) gets an 'L' tacked on at the end. – hallvabo Jan 28 '11 at 8:47
  • 4
    This can also be used to print floats to full precision – gnibbler Feb 19 '13 at 0:28

Store lookup tables as magic numbers

Say you want to hardcode a Boolean lookup table, like which of the first twelve English numbers contain an n.

0: False
1: True
2: False
3: False
4: False
5: False
6: False
7: True
8: False
9: True
10:True
11:True
12:False

Then, you can implement this lookup table concisely as:

3714>>i&1

with the resulting 0 or 1 being equal to False to True.

The idea is that the magic number stores the table as a bitstring bin(3714) = 0b111010000010, with the n-th digit (from the end) corresponding the the nth table entry. We access the nth entry by bitshifting the number n spaces to the right and taking the last digit by &1.

This storage method is very efficient. Compare to the alternatives

n in[1,7,9,10,11]
'0111010000010'[n]>'0'

You can have your lookup table store multibit entries that can be extracted like

 340954054>>4*n&15

to extract the relevant four-bit block.

  • Could we have an example result for the four-bit block? Did you use a rule for n-bit block? – JeromeJ Sep 14 '15 at 8:23
  • 7
    Hex might sometimes be even smaller. – Joonazan Feb 3 '16 at 21:34
  • 3
    This is useful for a lot of languages. – Cyoce Feb 11 '16 at 3:50
  • 1
    @Joonazan Hex is smaller for numbers over 999 999. – Mateen Ulhaq Jun 2 '17 at 7:57

Unless the following token starts with e or E. You can remove the space following a number.

For instance:

if i==4 and j==4:
    pass

Becomes:

if i==4and j==4:
    pass

Using this in complicated one line statements can save quite a few characters.

EDIT: as @marcog pointed out, 4or a will work, but not a or4 as this gets confused with a variable name.

  • 36
    if(i,j)==(4,4): is even shorter and in this special case if i==j==4: – gnibbler Jan 28 '11 at 0:14
  • 3
    Related: 4or a works, but not a or4 – marcog Jan 28 '11 at 0:15
  • 16
    0or also doesn't work (0o is a prefix for octal numbers). – Nabb Feb 2 '11 at 17:28
  • 5
    @Nabb Not that it matters anyways, since 0 or x is always gonna return x. Might as well cut out the 0 or. – ɐɔıʇǝɥʇuʎs Apr 6 '14 at 12:57
  • 3
    0or is fine as part of a longer number though. 10 or x is equivalent to 10or x. – trichoplax Apr 20 '14 at 22:39

A nice way to convert an iterable to list on Python 3:

imagine you have some iterable, like

i = (1,2,3,4)
i = range(4)
i = (x**2 for x in range(5))

But you need a list:

x=list(i)  #the default way
*x,=i      #using starred assignment -> 4 char fewer

It's very useful to make a list of chars out of a string

s=['a','b','c','d','e']
s=list('abcde')
*s,='abcde'
  • 1
    typing *s,='abcde' and then s crashes my interactive python3 with a segfault :( – daniero Jul 6 '15 at 18:41
  • @daniero Wow. Only on the interactive console? Sounds very weird. Try it on a clean console or report the bug – JBernardo Jul 6 '15 at 19:48
  • My Python 3.5 works fine. – NoOneIsHere Mar 10 '16 at 16:19
  • for i = (x**2 for x in range(5)) I get this code returned <generator object <genexpr> at 0x03321690> – george Jun 15 '16 at 14:27
  • 6
    And if you're doing this in an expression, you can do [*'abcde']. – Esolanging Fruit Jun 5 '17 at 0:58

Collapse two numerical loops into one

Say you're iterating over the cells of an m*n grid. Instead of two nested for loops, one for the row and one of the columns, it's usually shorter to use a single loop to iterate over the m*n cells of the grid. You can extract the row and column of the cell inside the loop.

Original code:

for i in range(m):
 for j in range(n):
  do_stuff(i,j)

Golfed code:

for k in range(m*n):
  do_stuff(k/n,k%n)

In effect, you're iterating over the Cartesian product of the two ranges, encoding the pair (i,j) as x=i*n+j. You've save a costly range call and a level of indentation inside the loop. The order of iteration is unchanged.

Use // instead of / in Python 3. If you refer to i and j many times, it may be faster to assign their values i=k/n, j=k%n inside the loop.

  • 3
    This is awesome. I had never realised this was possible! – theonlygusti Apr 2 '15 at 19:03
  • I saw this in the tips for JavaScript. It's a pretty useful trick in most languages. – Cyoce Jan 12 '16 at 6:59
  • 4
    For reference, to extend this to 3 loops: for i in range(m*n*o): do_stuff(i/n/o,i%(n*o)/o,i%o) – mbomb007 Oct 27 '16 at 14:48
  • 2
    For n loops: repl.it/EHwa – mbomb007 Oct 27 '16 at 16:33
  • In some cases, itertools.product can be much more concise than nested loops, especially when generating cartesian products. a1, a2, b1, b2 are examples of the cartesian product of 'ab' and '12' – Aaron3468 Mar 16 at 3:24

For integer n, you can write

  • n+1 as -~n
  • n-1 as ~-n

because the bit flip ~x equals -1-x. This uses the same number of characters, but can indirectly cut spaces or parens for operator precedence.

Compare:

while n-1:  #Same as while n!=1 
while~-n:

c/(n-1)
c/~-n

or f(n)+1
or-~f(n) 

(n-1)/10+(n-1)%10
~-n/10+~-n%10

The operators ~ and unary - are higher precedence than *, /, %, unlike binary +.

  • 11
    A variation on this trick I ran into today: -~-x saves one byte vs. (1-x). – Lynn Jul 15 '15 at 11:34
  • 4
    Another useful application is that a+b+1 can be more concisely written as a-~b. – Strigoides Jan 22 '17 at 11:51

Instead of range(x), you can use the * operator on a list of anything, if you don't actually need to use the value of i:

for i in[1]*8:pass

as opposed to

for i in range(8):pass

If you need to do this more than twice, you could assign any iterable to a variable, and multiply that variable by the range you want:

r=1,
for i in r*8:pass
for i in r*1000:pass

Note: this is often longer than exec"pass;"*8, so this trick should only be used when that isn't an option.

  • @proudhaskeller I think the point of the line you removed was that "In addition to the obvious character savings you get because [1]*8 is shorter than range(8), you also get to save a space because for i in[... is legal while for i in range... is not". – undergroundmonorail Aug 18 '14 at 17:13
  • oh, right, i didn't understand that. fixed now – proud haskeller Aug 18 '14 at 17:30
  • @MorganThrapp how does that save bytes over for i in[1]*8:pass? – undergroundmonorail Feb 1 '16 at 10:19
  • 6
    exec"pass;"*8 is significantly shorter. – DJMcSpookem May 19 '16 at 19:23
  • If this is being used in a list comprehension, this can be used to loop with a variable. Useful in lambdas. What I'm saying is instead of for i in[1]*n:a=(expression);, you do for a in[expression]*n: – Artyer Jun 4 '17 at 18:41

You can use the good old alien smiley face to reverse sequences:

[1, 2, 3, 4][::-1] # => [4, 3, 2, 1]

For ages it bothered me that I couldn't think of a short way to get the entire alphabet. If you use range enough that R=range is worth having in your program, then

[chr(i+97)for i in R(26)]

is shorter than the naive

'abcdefghijklmnopqrstuvwxyz'

, but otherwise it's longer by a single character. It haunted me that the clever one that required some knowledge of ascii values ended up being more verbose than just typing all the letters.

Until I saw this answer for My Daughter's Alphabet. I can't follow the edit history well enough to figure out if this genius was the work of the OP or if it was a suggestion by a commenter, but this is (I believe) the shortest way to create an iterable of the 26 letters in the Roman alphabet.

map(chr,range(97,123))

If case doesn't matter, you can strip off another character by using uppercase:

map(chr,range(65,91))

I use map way too much, I don't know how this never occurred to me.

  • 3
    Might use this in actual coding, I feel so stupid when hardcoding these things :') – ToonAlfrink Jun 7 '14 at 19:53
  • 31
    In actual coding, use string.lowercase -- that's what it's there for. – Kevin S Aug 13 '14 at 19:20
  • 1
    if you need both cases, the shortest way I know is filter(str.isalpha,map(chr,range(256))). It's just barely shorter than s=map(chr,range(256));s+=map(str.lower,s) – quintopia Nov 18 '15 at 3:40
  • @quintopia: Why 256 instead of 122 (ord('z'))? Aside from it being the same length... Also, if you need alphanumerics, replace str.isalpha in @quintopia's version with str.isalnum. (But if you only need one case, the whole 36-character string is no longer than filter(str.isalnum,map(chr,range(90))).) – Tim Pederick Dec 21 '15 at 5:36
  • 1
    If you going to be unfair and use range as R, my version is shorter than your original one: '%c'*26%tuple(R(97,123)) (only 24 chars) if you spell range it is just as long as the alphabet -- uppercase version is shorter – JBernardo Dec 21 '17 at 20:26

Extended iterable unpacking ("Starred assignment", Python 3 only)

The best way to explain this is via an example:

>>> a,*b,c=range(5)
>>> a
0
>>> b
[1, 2, 3]
>>> c
4

We've already seen a use for this — turning an iterable into a list in Python 3:

a=list(range(10))
*a,=range(10)

Here are a few more uses.

Getting the last element from a list

a=L[-1]
*_,a=L

In some situations, this can also be used for getting the first element to save on parens:

a=(L+[1])[0]
a,*_=L+[1]

Assigning an empty list and other variables

a=1;b=2;c=[]
a,b,*c=1,2

Removing the first or last element of a non-empty list

_,*L=L
*L,_=L

These are shorter than the alternatives L=L[1:] and L.pop(). The result can also be saved to a different list.

Tips courtesy of @grc

  • Wow! I have written a=1;L=[] so many times. It's amazing that you can save chars on something so straightforward as this. – xnor Dec 6 '14 at 9:16
  • @xnor That one's thanks to grc. With only one other element it's not as good (a,*L=1,), but it still saves one char :) – Sp3000 Dec 6 '14 at 9:20
  • don't forget you can also get both the first and last element of a list with a,*_,b=L – Cyoce Mar 3 '16 at 2:59

set literals in Python2.7

You can write sets like this S={1,2,3} This also means you can check for membership using {e}&S instead of e in S which saves one character.

  • 3
    And this also saves the character in ifs as there is no spaces (if{e}&S:) – Artyer Jun 4 '17 at 18:43

When you have two boolean values, a and b, if you want to find out if both a and b are true, use * instead of and:

if a and b: #7 chars

vs

if a*b: #3 chars

if either value is false, it will evaluate as 0 in that statement, and an integer value is only true if it is nonzero.

  • 9
    Or you could use &: a=b=False, a&b – ɐɔıʇǝɥʇuʎs Apr 9 '14 at 7:56
  • 3
    use + for or if you can guarantee a != -b – undergroundmonorail Apr 23 '15 at 1:18
  • 2
    | works in all situations. – CalculatorFeline May 31 '17 at 1:30
  • 1
    * instead of and/&& saves some bytes in many languages. – wastl Apr 30 at 20:48

Although python doesn't have switch statements, you can emulate them with dictionaries. For example, if you wanted a switch like this:

switch (a):
    case 1:
        runThisCode()
        break
    case 2:
        runThisOtherCode()
        break
    case 3:
        runThisOtherOtherCode()
        break

You could use if statements, or you could use this:

exec{1:"runThisCode()",2:"runThisOtherCode()",3:"runThisOtherOtherCode()"}[a]

To support a default value:

exec{1:"runThisCode()"}.get(a,"defaultCode()")

One other advantage of this is that if you do have redundancies, you could just add them after the end of the dictionary:

exec{'key1':'code','key2':'code'}[key]+';codeThatWillAlwaysExecute'

And if you just wanted to use a switch to return a value:

def getValue(key):
    if key=='blah':return 1
    if key=='foo':return 2
    if key=='bar':return 3
    return 4

You could just do this:

getValue=lambda key:{'blah':1,'foo':2,'bar',3}.get(key,4)
  • 2
    This is something i would deeply consider using in the wild. I do so miss my switch statements! +1 – HalosGhost Nov 19 '14 at 12:51
  • Although instead of using a dictionary with numbered keys in the first example, you should just use a list – Cyoce Oct 13 '16 at 19:25

loops up to 4 items may be better to supply a tuple instead of using range

for x in 0,1,2:

vs

for x in range(3):

Exploit Python 2 string representations

Python 2 lets you convert an object x to its string representation `x` at a cost of only 2 chars. Use this for tasks that are easier done on the object's string than the object itself.

Join characters

Given a list of characters l=['a','b','c'], one can produce ''.join(l) as `l`[2::5], which saves a byte.

The reason is that `l` is "['a', 'b', 'c']" (with spaces), so one can extract the letters with a list slice, starting that the second zero-indexed character a, and taking every fifth character from there. This doesn't work to join multi-character strings or escape characters represented like '\n'.

Concatenate digits

Similarly, given a non-empty list of digits like l=[0,3,5], one can concatenate them into a string '035' as `l`[1::3].

This saves doing something like map(str,l). Note that they must be single digits, and can't have floats like 1.0 mixed in. Also, this fails on the empty list, producing ].

Check for negatives

Now, for a non-string task. Suppose you have a list l of real numbers and want to test if it contains any negative numbers, producing a Boolean.

You can do

'-'in`l`

which checks for a negative sign in the string rep. This shorter than either of

any(x<0for x in l)
min(l+[0])<0   

For the second, min(l)<0 would fail on the empty list, so you have to hedge.

  • Concatenating single digits string slicing is also effective in Python 3, albeit less so: str(l)[2::5] is 12 bytes, versus 19 for ''.join(map(str,l)). An actual situation where this came up (where l was a generator statement, not a list) saved me just one byte... which is still worth it! – Tim Pederick Dec 21 '15 at 2:08

Ceil and Floor

If you ever want to get the rounded-up result for a division, much like you'd do with // for floor, you could use math.ceil(3/2) for 15 or the much shorter -(-3//2) for 8 bytes.

math.floor(n)   : 13 bytes+12 for import
n//1            : 4  bytes

math.ceil(n)    : 12 bytes+12 for import
-(-n//1)        : 8  bytes
  • 5
    This just saved me close to 20 bytes, thank you! – Morgan Thrapp Jan 13 '16 at 19:27
  • 1
    sometimes you can get away with n//1+1 instead of ceil but it does mean ceil(n)=n+1 but it should work for all non integer values – fejfo Dec 23 '17 at 20:26
  • round(x) is (x+.5)//1, +1 byte but the latter starts with a (, and if x is a sum consisting of a constant it can be useful. – user202729 Apr 28 at 5:27

A one line function can be done with lambda:

def c(a):
  if a < 3: return a+10
  else: return a-5

can be converted to (note missing space 3and and 10or)

c=lambda a:a<3and a+10or a-5
  • 19
    or c=lambda a:a+[-5,10][a<3]. the and/or trick is more useful when you are depending on the shortcircuit behaviour – gnibbler Feb 3 '11 at 13:23
  • 3
    In your function, else: can be dropped as return stops the execution of the function, so everything that follows is only executed if the if condition failed, aka if the else condition is true. Thus else can safely be ommited. (Explained in details for the neophytes out there) – JeromeJ Sep 14 '15 at 8:15

Use += instead of append and extend

A.append(B)  

can be shortened to:

A+=B,

B, here creates a one-element tuple which can be used to extend A just like [B] in A+=[B].


A.extend(B)

can be shortened to:

A+=B
  • 5
    In many (but not all) cases, return 0 or return 1 is equivalent to return False or return True. – undergroundmonorail Apr 16 '14 at 8:30
  • 5
    (1) only works if you already know the number is negative, in which case you can save a further 2 characters by simply using a minus sign. -x rather than x*-1. --8.32 rather than -8.32*-1. Or just 8.32... – trichoplax Apr 20 '14 at 22:56
  • Quoting the OP: Please post one tip per answer. – nyuszika7h Jun 23 '14 at 13:32
  • Note that in A+=B B is a tuple. – Erik the Outgolfer Jun 10 '16 at 7:52

Choosing one of two numbers based on a condition

You already know to use the list selection [x,y][b] with a Boolean b for the ternary expression y if b else x. The variables x, y, and b can also be expressions, though note that both x and y are evaluated even when not selected.

Here's some potential optimizations when x and y are numbers.

  • [0,y][b] -> y*b
  • [1,y][b] -> y**b
  • [x,1][b] -> b or x
  • [x,x+1][b] -> x+b
  • [x,x-1][b] -> x-b
  • [1,-1][b] -> 1|-b
  • [x,~x][b] -> x^-b
  • [x,y][b] -> x+z*b (or y-z*b), where z=y-x.

You can also switch x and y if you can rewrite b to be its negation instead.

Change import * to import*


If you haven't heard, import* saves chars!

from math import*

is only 1 character longer than import math as m and you get to remove all instances of m.

Even one time use is a saver!

Use ~ to index from the back of a list

If L is a list, use L[~i] to get the i'th element from the back.

This is the i'th element of the reverse of L. The bit complement ~i equals -i-1, and so fixes the off-by-one error from L[-i].

PEP448 – Additional Unpacking Generalizations

With the release of Python 3.5, manipulation of lists, tuples, sets and dicts just got golfier.

Turning an iterable into a set/list

Compare the pairs:

set(T)
{*T}

list(T)
[*T]

tuple(T)
(*T,)

Much shorter! Note, however, that if you just want to convert something to a list and assign it to a variable, normal extended iterable unpacking is shorter:

L=[*T]
*L,=T

A similar syntax works for tuples:

T=*L,

which is like extended iterable unpacking, but with the asterisk and comma on the other side.

Joining lists/tuples

Unpacking is slightly shorter than concatenation if you need to append a list/tuple to both sides:

[1]+T+[2]
[1,*T,2]

(1,)+T+(2,)
(1,*T,2)

Printing the contents of multiple lists

This isn't limited to print, but it's definitely where most of the mileage will come from. PEP448 now allows for multiple unpacking, like so:

>>> T = (1, 2, 3)
>>> L = [4, 5, 6]
>>> print(*T,*L)
1 2 3 4 5 6

Updating multiple dictionary items

This probably won't happen very often, but the syntax can be used to save on updating dictionaries if you're updating at least three items:

d[0]=1;d[1]=3;d[2]=5
d={**d,0:1,1:3,2:5}

This basically negates any need for dict.update.

  • 3
    This looks worse than Perl, but it works... – Mega Man Jun 25 '16 at 5:52
>>> for i in range(x):s+=input()

if value of i is useless:

>>> for i in[0]*x:s+=input()

or

>>> exec's+=input();'*x
  • 8
    You can make the second example into for i in[0]*x:s+=input() to save another space. Also, you can remove the space between the exec and the first quotation mark to get exec's+=input();'*x – Justin Peel Apr 19 '11 at 6:12
  • shouldn't the second line be: for i in[0]*x:s+=input() – micsthepick Aug 5 '15 at 7:47
  • Dupe (newer but more upvotes) – user202729 Apr 17 at 16:07

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.