Of course! "Golfing" in Python refers to the practice of writing code in the most concise way possible, character by character. It's a fun and challenging puzzle-like activity that often requires deep knowledge of Python's syntax, libraries, and quirks.
Here’s a comprehensive guide to Python golfing, from basic techniques to advanced tricks.
The Golden Rule of Golfing
Read the problem carefully. The goal is not just to make the code short, but to make it short and correct. A clever one-liner that fails on edge cases is worse than a slightly longer, robust solution.
Level 1: The Basics (Easy Savings)
These are the most common and effective techniques for shaving off characters.
Use Shorter Variable Names
This is the most obvious one. Use single-letter variables or abbreviations.
- Before:
for i in range(10): print(i) - After:
for i in range(10):print(i)(saving a space is also key!)
Remove Unnecessary Whitespace
Python is whitespace-sensitive, but not all whitespace is required.
- Spaces around operators:
a = b + c->a=b+c - Spaces after commas:
f(a, b)->f(a,b) - Spaces after colons in loops/conditionals:
if a==b: pass->if a==b:pass - Spaces after function definitions:
def f(): pass->def f():pass - Newlines: Often, you can chain statements on one line with .
a=1;b=2;print(a+b)
Use lambda for Simple Functions
If a function is just one return statement, a lambda is often shorter.
- Before:
def f(x): return x*x
- After:
f=lambda x:x*x
This saves 6 characters (
def f(and): return).
Use List Comprehensions
Instead of a for loop that builds a list, use a list comprehension. They are more concise and often faster.
- Before:
s = [] for i in range(10): s.append(i*i) - After:
s=[i*i for i in range(10)]
This saves 10 characters.
Level 2: Intermediate Tricks (Significant Savings)
These techniques involve clever use of Python's features and libraries.
Leverage the eval Function
The eval() function can be a golfer's best friend. It parses and executes a string as Python code. This is extremely powerful for mathematical problems.
-
Problem: Calculate the sum of
aandb. -
Before:
print(a+b) -
After:
eval('a+b')This is only useful if the string'a+b'is shorter thana+b, which it isn't in this case. But for more complex expressions, it can be a huge win. -
Problem: Calculate
a^b(bitwise XOR). -
Before:
print(a^b) -
After:
eval('a**b')(No, this is exponentiation) Let's try again. -
Better After:
eval('a^b')(Same length, but shows the concept) -
*Real Example (Calculate `ab+c`):**
print(a*b+c)(9 chars)eval('a*b+c')(11 chars) -> Not a win.eval('a*b+c')is a win when the expression is long and you can generate it dynamically.
Use Ternary Conditional Operator
For a simple if-else, the ternary operator is much shorter.
- Before:
x = a if a > b else b - After:
x=[b,a][a>b]This is a classic golfing trick. It creates a list[b, a]and picks the element at indexa > b. SinceTrueis1andFalseis0, this works perfectly. It's often shorter than thex=a if a>b else bsyntax.
Abuse Truthy/Falsy Values
In Python, many objects have a "truthiness".
0,0, ,[], , areFalse.- Almost everything else is
True.
You can use this to avoid writing == 0 or .
- Before:
if n == 0: print("Zero") - After:
if not n:print("Zero")(saves 3 chars)
Use map and filter
These functions apply another function to every item in an iterable (or a filtered subset of it).
- Problem: Square every number in a list
l. - Before:
[i*i for i in l] - After:
map(lambda i:i*i,l)(Often needs to be wrapped inlist()to see the result, e.g.,list(map(...)), so this isn't always a win).
Use the Walrus Operator (Python 3.8+)
This operator assigns a value to a variable as part of an expression. This is a game-changer for golfing.
- Problem: Read a line from stdin, convert to int, and print it.
- Before:
i=int(input()) print(i)
- After:
print(i:=int(input()))
This saves 5 characters by combining two lines into one.
Level 3: Advanced & Obscure Tricks (The Pro Moves)
This is where you dive deep into Python's internals and less common features.
Use exec for Repetition
Similar to eval, exec runs a block of code. You can use it to repeat a command without a loop.
- Problem: Print "Hello" 5 times.
- Before:
for _ in' ':print("Hello")(Uses the 5 spaces in the string to loop 5 times) - After:
exec('print("Hello");'*5)(A very common golfing pattern)
Use String/Number Concatenation for Repetition
You can multiply strings or numbers to create a sequence.
- Problem: Loop 10 times.
- Before:
for i in range(10): - After:
for i in' ':(Uses the 10 spaces) - Even After:
for i in 1e10:(Creates a float0and iterates over its digits, which is a bit weird but works)
Abuse print's sep and end Parameters
The print function is incredibly flexible. sep is the separator between items, and end is what's printed at the end.
- Problem: Print "a" and "b" with no space between them.
- Before:
print("a",end="");print("b") - After:
print("a","b",end="")(Saves many characters)
Use join with a Separator
A common pattern is to join a list of items.
- Problem: Join a list of numbers
lwith a space. - Before:
' '.join(map(str, l)) - After:
*l,(Unpacking the list intoprintis often shorter)print(*l) # Prints items with a space separator
Or, if you need the string itself:
print(' '.join(l))(Works iflcontains strings)
Use globals() and locals()
These dictionaries hold the global and local variables in the current scope. You can access or modify variables by name as strings.
- Problem: Assign the value
10to the variablex. - Before:
x=10 - After:
globals()['x']=10(Much longer, but shows the concept. It's useful when the variable name is dynamic).
The Trick
This is a famous golfing trick. -~x is equivalent to x + 1.
-
~xis the bitwise NOT ofx, which is-x - 1. -
So,
-~xis-(-x - 1), which simplifies tox + 1. -
Problem: Increment
x. -
Before:
x+=1 -
After:
x=-~x(Same length, but a fun trick. Can be useful in expressions).
Putting It All Together: A Case Study
Problem: Given a number n, print n to the power of n.
The "Normal" Solution (28 chars)
n=int(input()) print(n**n)
Golfing it Step-by-Step
-
Combine lines with the walrus operator: We can read
nand print in one go.print(n:=int(input())**n)
This is 19 characters. A big improvement!
-
Can we make the input part shorter?
input()is 6 chars. Is there a shorter way to get input? No, not really. What about the conversion?int()is 4 chars. -
Let's look at the core logic:
n**n. Is there a shorter way to write exponentiation? No, is the standard. What aboutpow(n,n)? That's also 6 chars, same asn**n. -
Let's re-examine the whole expression.
print(n:=int(input())**n)print(...)(5)n:=(3)int(input())(10)- (2)
n(1)- Total: 5 + 3 + 10 + 2 + 1 = 21. Wait, my count was off. Let's count again.
printnintinputn= 19 characters. Yes, it's 19.
-
Is there a completely different approach? What if we don't use the walrus operator?
print(int(input())**int(input()))
This is 21 characters. Worse.
i=int(input()) print(i**i)
This is 16 characters! This is shorter!
Conclusion: Sometimes the most obvious golfing tricks (like the walrus operator) don't lead to the shortest solution. The simplest approach can sometimes be the best. The final golfed answer is i=int(input());print(i**i) at 16 characters.
Where to Practice
The best place to practice is on code-golf.io or golf.shinh.org. These sites have hundreds of problems specifically designed for code golfing in many languages, including Python.
Happy golfing
