3 Comments
User's avatar
Wyrd Smythe's avatar

Good post, and I'm looking forward to part two. I love decorators in Python. They were a bit tricky to figure out from the manual, but doing it sure opened the door to some great tricks. I've used them as timing wrappers for functions, recording both the count of times called and the total time used in the function (or functions). And I love how you can add attributes and methods to the decorator itself, giving some access to its internals (like how @property does).

Expand full comment
Bruce's avatar

I don't know why you have to use __closure__[0].cell_contents.

It seems a bit abstract and obscure.

Why not just attach the history directly?

```python

def print_with_memory():

history = []

def inner(some_obj):

history.append(some_obj)

print(some_obj)

inner.history = history

return inner

print_ = print_with_memory()

print_("A")

print_("B")

print(print_.history)

```

I don't know how to enter Python script. It keeps messing up the indents!

Expand full comment
Stephen Gruppetta's avatar

I agree it’s abstract and obscure, and you’ll notice I only use it temporarily as I build towards the final solutions (see also Parts 3-7 that are in the follow up post), which no longer use this. As with all dunder attributes, they’re not meant to be used directly!

The reason I show this is to demonstrate what happens behind the scenes for those who are curious to know a bit on how this is implemented in Python (CPython).

Personally, I’m always curious to peek behind the scenes as it helps me understand better what’s happening. So I tend to include these “behind the scenes” when writing, too.

But yes, this is not a solution you want to use in your actual code!

Expand full comment