3 ms·
For all of Python's magic hackery that it lets you inject it feels like there are still some obvious 'holes'. The one that bites me a lot is: I want to easily
by ajkjk 5y ago
For all of Python's magic hackery that it lets you inject it feels like there are still some obvious 'holes'.
The one that bites me a lot is: I want to easily be able to write a decorator that accesses variables on a particular _instance_ of a class (such as a cached return value), and I want to take a Lock when I do it.
But since decorators are defined on the class method, not the instance, it has to do a bunch of work when the function runs: look at the instance, figure out if the lock is defined, if not define it (using a global lock?), take the lock, then do whatever internal processing it wants. It feels like decorators should have a step that runs at `__init__` time to do per-instance setup but instead I have to figure it out myself.
- Spivak 5y agoI'm so confused. from functools import wraps from threading import Lock def my_decorator(f): # Do whatever you want to set up the lock. lock = Lock() @wraps(f) def wrapper(self, *args, **kwargs): # Do whatever with the lock. lock.acquire() # Do whatever you want with the instance. print(self.greeting) return f(self, *args, **kwargs) return wrapper class MyClass: def __init__(self): self.greeting = "Hello World!" @my_decorator def my_method(self): print("And all who inhabit it.") >>> MyClass().my_method() Hello World! And all who inhabit it. Edit: Wait do you want the decorator, before it ever runs, to add a property self.lock? Are you sure you don't want this to be a class decorator that messes with __init__? Because you can 100% wrap init to do that kind of set up.
- ajkjk 5y agoThe problem is that `lock = Lock()` is shared across all instances of the class, which creates contention if there are many of them. To solve this you need to save a per-instance lock, so yes to "Wait do you want the decorator, before it ever runs, to add a property self.lock". An example usecase is writing a @cached decorator that behaves well in multithreaded programs and can be used on classes that have many instances, with the caching happening per-instance.