In the current python codebases, there are a lot of decorators with parameters, 
and their code in most cases contains a lot of code boilerplates. The purpose 
of this feature is to add `decorator_with_params` (I think the name can be 
changed to smth better) function to `functools` module. This function will 
allow using a decorated function as a simple decorator and decorator with 
parameter. 

I believe the real example will bring more context, for instance, 
`typing._tp_cache` function can be rewritten from:
```
def _tp_cache(func=None, /, *, typed=False):
    """Internal wrapper caching __getitem__ of generic types with a fallback to
    original function for non-hashable arguments.
    """
    def decorator(func):
        cached = functools.lru_cache(typed=typed)(func)
        _cleanups.append(cached.cache_clear)

        @functools.wraps(func)
        def inner(*args, **kwds):
            try:
                return cached(*args, **kwds)
            except TypeError:
                pass
            return func(*args, **kwds)
        return inner

    if func is not None:
        return decorator(func)

    return decorator
```
To
```
@decorator_with_params
def _tp_cache(func, /, *, typed=False):
    """Internal wrapper caching __getitem__ of generic types with a fallback to
    original function for non-hashable arguments.
    """
    cached = functools.lru_cache(typed=typed)(func)
    _cleanups.append(cached.cache_clear)

    @functools.wraps(func)
    def inner(*args, **kwds):
        try:
            return cached(*args, **kwds)
        except TypeError:
            pass  # All real errors (not unhashable args) are raised below.
        return func(*args, **kwds)

    return inner
```

And `_tp_cache` can be used as:
```
    @_tp_cache(typed=True)
    def __getitem__(self, parameters):
        return self._getitem(self, parameters)
    ...
    @_tp_cache
    def __getitem__(self, parameters):
        return self._getitem(self, parameters)
```

Proposed implementation is quite simple (I used it in a lot of projects):
```
def decorator_with_params(deco):
    @wraps(deco)
    def decorator(func=None, /, *args, **kwargs):
        if func is not None:
            return deco(func, *args, **kwargs)

        def wrapper(f):
            return deco(f, *args, **kwargs)

        return wrapper

    return decorator
```

I believe it will be a great enhancement for the Python standard library and 
will save such important indentations.

I have already opened an issue https://bugs.python.org/issue42455 (Sorry about 
that I didn't know that smth like python-ideas exists).
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OIRAB3QA4AAD3JGH2S5HMGCPDLGG7T52/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to