-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Let lru_cache be used as a decorator with no arguments #80953
Comments
Follow the lead of the dataclasses module and allow lru_cache() to be used as a straight decorator rather than as a function that returns a decorator. Both of these would now be supported: @lru_cache
def f(x):
...
@lru_cache(maxsize=256)
def f(x):
... |
I do not like mixing decorators and decorator fabrics. But this can of worms has already been open by dataclasses. The question is whether we want to extend this design to the rest of the stdlib. lru_cache() resisted this change for a long time. |
The 90% use case with dataclasses is satisfied with just "@DataClass", and perhaps the target user there is less sophisticated. But the main difference between @DataClass and @lru_cache is that all of the parameters to @DataClass are keyword-only. Which I did because they are mostly all booleans, and "@DataClass(True, False, True)" isn't very helpful. That's not the case with @lru_cache. Whether that makes a difference for this issue in particular, I'm not sure. I agree that this violates "only one way to do it". But I haven't seen anyone use "@DataClass()", and I've also never seen anyone be confused by the fact that once you want parameters, you change to using parens. For the dataclass case, I think that working both ways has been helpful. |
I'm generally ok with such APIs. It seems needless to require @lru_cache()
def f(): ... when a simple decorator would suffice. I think I might decide otherwise in cases where almost all usages require arguments, but if the no-arguments case is common (and there is no ambiguity in the arguments), then I prefer not requiring parentheses. |
At Pycon today, I mostly got all positive feedback on this. Apparently py.test already follows this pattern. Another developer said they found the () to be distracting and would welcome not having to use them. |
FWIW, I've followed this pattern (one function is both decorator and factory) in my own code for quite a while. I've never found it confusing nor has anyone else (that I'm aware) that has used those decorators. One reason I've done decorators this way is because the empty parentheses are a visual distraction to readers. They also imply to readers that more is going on than really is. So I'm in favor of Raymond's plan. |
As to the issue of positional vs. keyword arguments, keyword arguments make the implementation easier in some cases. Otherwise I haven't seen positional arguments cause much of a problem. |
To clarify, I am not opposing this feature. I had doubts because if the memory does not betray me similar propositions for lru_cache or other decorator fabrics were rejected in past. But times change. |
I am +1 to this. Making it easier for the case of decorator factories that are called with all the defaults is a very common pattern in the wild. There are even known idioms for how to reduce the indentation of the naive approach (returning partials of the factory). In particular for lru_cache, my experience is that every time I teach this feature, people are confused initially about the '()' at the end of the call. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: