Can You Write Python Without def? I Tried It.

I challenged myself to ditch Python’s def keyword completely

Can You Write Python Without def? I Tried It.
Photo by Pascal Scholl on Unsplash

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:

  1. No def keyword allowed. Anywhere.
  2. The code should remain readable. No obfuscation or deliberately unreadable tricks.
  3. 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 a map)
  • 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.

Photo by Abin James on Unsplash