Reputation: 4317
There are many answers here on how to detect if a python decorator is used with or without arguments. They typically look like this:
class MyDecorator(object):
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
# no arguments
else:
# arguments
But now I have the following use-case:
@MyDecorator(lambda x:2*x)
def foo():
pass
Which is wrongly detected as a 'no-argument' case.
Is there a way to detect this situation as well?
[edit: Added missing 'self' parameter]
Upvotes: 4
Views: 1123
Reputation: 1121644
The __init__
method requires a self
parameter:
class MyDecorator(object):
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
# no arguments
else:
# arguments
Without it you always have one argument at least and it will not be callable; it is the decorator instance instead. In other words, without an explicit self
, *args
will be two elements long when you pass in the argument and it'll be args[1]
you wanted to test.
Upvotes: 1
Reputation: 80031
Yes, but it will remain slightly hacky. The trick is to use named arguments. Besides that there is no clean way to differentiate between the different callables.
class MyDecorator(object):
def __init__(self, *args, **kwargs):
if kwargs:
# arguments
print 'got %r as arguments'
else:
callable, = args
@MyDecorator(some_function=lambda x:2*x)
def foo():
pass
Upvotes: 2