简体   繁体   中英

Python decorator with optional callable argument

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]

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM