Can You Write Python Without def? I Tried It.
I challenged myself to ditch Python’s def keyword completely

Most Python code starts with def
— but what if you never used it at all?
Can You Write Python Without def
? I Tried It.
Can You Really Write Python Without def
?
The first thing most of us learn in Python is how to define a function using def
. It's foundational, right?
def greet(name):
return f"Hello, {name}!"
But one day, while deep in a thought spiral about Python’s quirks, I asked myself: What if I tried to write an entire Python script without ever using def
?
That one question led me down a weird and wonderful rabbit hole. Along the way, I discovered some clever uses of lambdas, callable classes, and even some unexpected hacks that work surprisingly well — until they don’t.
So… can you write Python without def
? Short answer: yes.
Should you? Well, that’s where things get interesting.
The Rules of the Challenge
For this experiment, I set three simple rules:
- No
def
keyword allowed. Anywhere. - The code should remain readable. No obfuscation or deliberately unreadable tricks.
- It must include logic beyond one-liners — think conditions, iterations, and modularity.
Spoiler: I broke some of my own rules. But that’s part of the fun.
Tool #1: Lambda Functions
Naturally, the first tool that comes to mind when avoiding def
is the humble lambda.
add = lambda x, y: x + y
print(add(2, 3)) # Output: 5
Great for simple one-liners, right? But what if you want something more involved?
Let’s say you want a function that prints a greeting and logs it. Here’s what happens when you try it in a lambda:
greet = lambda name: (print(f"Hello, {name}"), log(name))
But Python lambdas can only contain expressions — not statements like if
, for
, or print
as standalone operations. This quickly becomes limiting.
So… what’s next?
Tool #2: Functions via types.FunctionType
Feeling cheeky? You can build functions manually using the types
module.
import types
code = compile('return x + y', '<string>', 'exec')
add = types.FunctionType(code.co_consts[0], globals())
print(add(3, 4)) # Output: 7
But this is painful to read, harder to debug, and violates our readability rule. Not exactly production-friendly.
Tool #3: Callable Classes
When all else fails, Python’s object-oriented features come to the rescue.
class Multiply:
def __call__(self, x, y):
return x * y
multiply = Multiply()
print(multiply(3, 5)) # Output: 15
es, there’s a def
inside the class. But — plot twist — you didn’t write it. If we wanted to avoid writing def
ourselves, this technically passes.
Better yet, you can dynamically create the class with type
:
Multiply = type("Multiply", (), {
"__call__": lambda self, x, y: x * y
})
multiply = Multiply()
print(multiply(2, 4)) # Output: 8
Readable? Arguably.
Efficient? Debatable.
Avoids def
? Absolutely.
Tool #4: functools.partial
and Higher-Order Functions
Higher-order functions are also useful when you’re avoiding defining anything yourself.
from functools import partial
def add(x, y): return x + y # Just for example, imagine this was imported
add_five = partial(add, 5)
print(add_five(10)) # Output: 15
Wait — we cheated again! That def
is back.
But if you’re working with existing functions (from libraries or modules), partial
becomes an excellent way to remixfunctionality without defining anything new.
So in a strict “no-def writing” project, you can get pretty far just by composing, currying, or chaining functions that already exist.
Tool #5: Closures with Lambdas
Want to simulate stateful behavior without a class or def
? Closures can help.
def counter():
count = [0]
return lambda: (count.__setitem__(0, count[0] + 1), count[0])[1]
increment = counter()
print(increment()) # 1
print(increment()) # 2
Yes, we cheated again with def
, but if we predefine this kind of logic elsewhere (or pull it from a module), you can still simulate closures with lambdas and mutable containers.
The Real Takeaway
So, can you write Python without def
?
Technically, yes — but you’ll:
- Rely heavily on lambdas (which are limited)
- Hack your way through classes and metaprogramming
- Lose readability fast
- Probably question your life choices
But more importantly, you’ll learn a lot about how Python treats functions — as objects, as values, and as first-class citizens.
This experiment taught me more about Python’s internals than a dozen tutorials. I now have a deeper appreciation for how powerful and flexible function definitions are — and why Python’s def
exists in the first place.
When You Might Avoid def
(Seriously)
There are rare cases where avoiding def
actually makes sense:
- One-liner utilities (e.g.,
lambda x: x.strip()
in amap
) - Dynamic behavior in frameworks (e.g., decorators or factories)
- When writing obfuscated code competitions (please don’t)
But for maintainable, scalable, production-level Python? Stick with def
. It's elegant, expressive, and (most of the time) the right tool for the job.
Final Thoughts: Don’t Avoid def
— Understand It Deeper
Avoiding def
is like running a marathon barefoot. It's possible. It might even be enlightening. But it's not how you’d want to build something serious.
Still, weird constraints can stretch your understanding in wonderful ways.
So, the next time you write def
, take a second to appreciate the simplicity it brings. Behind that humble keyword is a whole world of functional programming, closures, object orientation, and Pythonic elegance.
If you liked this article, maybe try this challenge yourself:
Can you write a mini CLI tool in Python without using def
? I’d love to see what you come up with.
