Merging python decorators with arguments into a single one

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
9
down vote

favorite
1












I'm using two different decorators from two different libraries. Lets say: @decorator1(param1, param2) and @decorator2(param3, param4). That I often use in many function as:



from moduleA import decorator1
from moduleB import decorator2

@decorator2(foo='param3', bar='param4')
@decorator1(name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...


Since it happens everytime, I would like to create a custom decorator that handle both of them. Something like:



@mycustomdecorator(name='param1', state='param2', 
foo='param3', bar='param4')
def myfunc(funcpar1, funcpar2):
...


How to achieve that?










share|improve this question























  • I don't think is the same, in post you mentioned the @customdecorator is receiving decorators. It will not be this case.
    – Lin
    1 hour ago











  • You can easily extend this answer to add parameters though.
    – Aran-Fey
    1 hour ago










  • can you please instead mark as duplicated, add the extension, since I'm not being able achieve that from that answer.
    – Lin
    1 hour ago










  • I don't think we should have two separate Q&As for merging decorators with and without arguments, so I'm going to post a more complete answer in the other question.
    – Aran-Fey
    1 hour ago






  • 1




    Possible duplicate of Can I combine two decorators into a single one in Python?
    – Julian Camilleri
    1 hour ago














up vote
9
down vote

favorite
1












I'm using two different decorators from two different libraries. Lets say: @decorator1(param1, param2) and @decorator2(param3, param4). That I often use in many function as:



from moduleA import decorator1
from moduleB import decorator2

@decorator2(foo='param3', bar='param4')
@decorator1(name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...


Since it happens everytime, I would like to create a custom decorator that handle both of them. Something like:



@mycustomdecorator(name='param1', state='param2', 
foo='param3', bar='param4')
def myfunc(funcpar1, funcpar2):
...


How to achieve that?










share|improve this question























  • I don't think is the same, in post you mentioned the @customdecorator is receiving decorators. It will not be this case.
    – Lin
    1 hour ago











  • You can easily extend this answer to add parameters though.
    – Aran-Fey
    1 hour ago










  • can you please instead mark as duplicated, add the extension, since I'm not being able achieve that from that answer.
    – Lin
    1 hour ago










  • I don't think we should have two separate Q&As for merging decorators with and without arguments, so I'm going to post a more complete answer in the other question.
    – Aran-Fey
    1 hour ago






  • 1




    Possible duplicate of Can I combine two decorators into a single one in Python?
    – Julian Camilleri
    1 hour ago












up vote
9
down vote

favorite
1









up vote
9
down vote

favorite
1






1





I'm using two different decorators from two different libraries. Lets say: @decorator1(param1, param2) and @decorator2(param3, param4). That I often use in many function as:



from moduleA import decorator1
from moduleB import decorator2

@decorator2(foo='param3', bar='param4')
@decorator1(name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...


Since it happens everytime, I would like to create a custom decorator that handle both of them. Something like:



@mycustomdecorator(name='param1', state='param2', 
foo='param3', bar='param4')
def myfunc(funcpar1, funcpar2):
...


How to achieve that?










share|improve this question















I'm using two different decorators from two different libraries. Lets say: @decorator1(param1, param2) and @decorator2(param3, param4). That I often use in many function as:



from moduleA import decorator1
from moduleB import decorator2

@decorator2(foo='param3', bar='param4')
@decorator1(name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...


Since it happens everytime, I would like to create a custom decorator that handle both of them. Something like:



@mycustomdecorator(name='param1', state='param2', 
foo='param3', bar='param4')
def myfunc(funcpar1, funcpar2):
...


How to achieve that?







python python-decorators






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 55 mins ago

























asked 1 hour ago









Lin

359112




359112











  • I don't think is the same, in post you mentioned the @customdecorator is receiving decorators. It will not be this case.
    – Lin
    1 hour ago











  • You can easily extend this answer to add parameters though.
    – Aran-Fey
    1 hour ago










  • can you please instead mark as duplicated, add the extension, since I'm not being able achieve that from that answer.
    – Lin
    1 hour ago










  • I don't think we should have two separate Q&As for merging decorators with and without arguments, so I'm going to post a more complete answer in the other question.
    – Aran-Fey
    1 hour ago






  • 1




    Possible duplicate of Can I combine two decorators into a single one in Python?
    – Julian Camilleri
    1 hour ago
















  • I don't think is the same, in post you mentioned the @customdecorator is receiving decorators. It will not be this case.
    – Lin
    1 hour ago











  • You can easily extend this answer to add parameters though.
    – Aran-Fey
    1 hour ago










  • can you please instead mark as duplicated, add the extension, since I'm not being able achieve that from that answer.
    – Lin
    1 hour ago










  • I don't think we should have two separate Q&As for merging decorators with and without arguments, so I'm going to post a more complete answer in the other question.
    – Aran-Fey
    1 hour ago






  • 1




    Possible duplicate of Can I combine two decorators into a single one in Python?
    – Julian Camilleri
    1 hour ago















I don't think is the same, in post you mentioned the @customdecorator is receiving decorators. It will not be this case.
– Lin
1 hour ago





I don't think is the same, in post you mentioned the @customdecorator is receiving decorators. It will not be this case.
– Lin
1 hour ago













You can easily extend this answer to add parameters though.
– Aran-Fey
1 hour ago




You can easily extend this answer to add parameters though.
– Aran-Fey
1 hour ago












can you please instead mark as duplicated, add the extension, since I'm not being able achieve that from that answer.
– Lin
1 hour ago




can you please instead mark as duplicated, add the extension, since I'm not being able achieve that from that answer.
– Lin
1 hour ago












I don't think we should have two separate Q&As for merging decorators with and without arguments, so I'm going to post a more complete answer in the other question.
– Aran-Fey
1 hour ago




I don't think we should have two separate Q&As for merging decorators with and without arguments, so I'm going to post a more complete answer in the other question.
– Aran-Fey
1 hour ago




1




1




Possible duplicate of Can I combine two decorators into a single one in Python?
– Julian Camilleri
1 hour ago




Possible duplicate of Can I combine two decorators into a single one in Python?
– Julian Camilleri
1 hour ago












3 Answers
3






active

oldest

votes

















up vote
6
down vote



accepted










I would argue that you shouldn't - using the original names for the decorators gives much better readability.



However, if you really want to, you can do it like this:



import functools

from moduleA import decorator1
from moduleB import decorator2

def my_decorator(foo, bar, name, state):
def inner(func):
@decorator2(foo=foo, bar=bar)
@decorator1(name=name, state=state)
@functools.wraps(func) # Not required, but generally considered good practice
def newfunc(*args, **kwargs)
return func(*args, **kwargs)
return newfunc
return inner

@my_decorator(foo='param3', bar='param4', name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...


It's simple really - just write a decorator that returns another decorator which will have it's inner function decorated with the other two decorators ;)



It might also be a good idea to use functools.wraps, for the sake of good habits. It's standard library and helps a lot with debugging and interactive console use: https://docs.python.org/3.7/library/functools.html



In general though, I'd say the one extra line of code is more than worth the clarity of using the decorators separately. You'll thank yourself when you read your own code in 3 more months.






share|improve this answer


















  • 1




    You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
    – Aran-Fey
    47 mins ago










  • You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
    – Jacco van Dorp
    45 mins ago










  • While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
    – bruno desthuilliers
    44 mins ago










  • If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
    – Jacco van Dorp
    41 mins ago











  • @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
    – Mad Physicist
    37 mins ago

















up vote
2
down vote













This is just simple function composition, where decorator1 and decorator2 are returning the functions you want to compose. The real work can be abstracted out into a function compose.



# In the special case of composing decorators, the lambda expression
# only needs to be defined with a single argument, like
#
# lambda func: f(g(func))
#
# but I show a more general form.
def compose(f, g):
return lambda *args, **kwargs: f(g(*args, **kwargs))

def customdecorator(foo, bar, name, state):
return compose(decorator2(foo=foo, bar=bar),
decorator1(name=name, state=state))





share|improve this answer





























    up vote
    0
    down vote













    Decorator is nothing more than a syntax sugar to the syntax like func = decorator(func).



    So, you can easily make your own decorator that does whatever you want with the following syntax:



    def mycustomdecorator(foo, bar, name, state)
    def innerdecorator(func):
    func = decorator1(foo=foo, bar=bar)(func)
    func = decorator2(name=name, state=state)(func)
    def wrapper(*args, **kwargs):
    func(*args, **kwargs)
    return wrapper
    return innerdecorator


    After that, you should be able to use @mycustomdecorator with no hassle. Let me know if this works, I didn't test it but theoretically it should.



    What's the magic there: first, we need to retrieve parameters for our decorators. This way, we are able to pass them on into nested function. Then, we are accepting our function as an argument, and the last, we are getting parameters for our function. We can nest our def-s as much as we need.






    share|improve this answer










    New contributor




    Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.

















    • That's not quite right. You have too many nested functions there.
      – Aran-Fey
      45 mins ago










    • Can you elaborate, please?
      – Ð”митрий Клименко
      44 mins ago






    • 1




      If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
      – Aran-Fey
      42 mins ago










    • Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
      – Ð”митрий Клименко
      31 mins ago






    • 1




      (The wrong part is that wrapper should call, not return, func.)
      – chepner
      18 mins ago










    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52517273%2fmerging-python-decorators-with-arguments-into-a-single-one%23new-answer', 'question_page');

    );

    Post as a guest






























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    6
    down vote



    accepted










    I would argue that you shouldn't - using the original names for the decorators gives much better readability.



    However, if you really want to, you can do it like this:



    import functools

    from moduleA import decorator1
    from moduleB import decorator2

    def my_decorator(foo, bar, name, state):
    def inner(func):
    @decorator2(foo=foo, bar=bar)
    @decorator1(name=name, state=state)
    @functools.wraps(func) # Not required, but generally considered good practice
    def newfunc(*args, **kwargs)
    return func(*args, **kwargs)
    return newfunc
    return inner

    @my_decorator(foo='param3', bar='param4', name='param1', state='param2')
    def myfunc(funcpar1, funcpar2):
    ...


    It's simple really - just write a decorator that returns another decorator which will have it's inner function decorated with the other two decorators ;)



    It might also be a good idea to use functools.wraps, for the sake of good habits. It's standard library and helps a lot with debugging and interactive console use: https://docs.python.org/3.7/library/functools.html



    In general though, I'd say the one extra line of code is more than worth the clarity of using the decorators separately. You'll thank yourself when you read your own code in 3 more months.






    share|improve this answer


















    • 1




      You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
      – Aran-Fey
      47 mins ago










    • You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
      – Jacco van Dorp
      45 mins ago










    • While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
      – bruno desthuilliers
      44 mins ago










    • If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
      – Jacco van Dorp
      41 mins ago











    • @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
      – Mad Physicist
      37 mins ago














    up vote
    6
    down vote



    accepted










    I would argue that you shouldn't - using the original names for the decorators gives much better readability.



    However, if you really want to, you can do it like this:



    import functools

    from moduleA import decorator1
    from moduleB import decorator2

    def my_decorator(foo, bar, name, state):
    def inner(func):
    @decorator2(foo=foo, bar=bar)
    @decorator1(name=name, state=state)
    @functools.wraps(func) # Not required, but generally considered good practice
    def newfunc(*args, **kwargs)
    return func(*args, **kwargs)
    return newfunc
    return inner

    @my_decorator(foo='param3', bar='param4', name='param1', state='param2')
    def myfunc(funcpar1, funcpar2):
    ...


    It's simple really - just write a decorator that returns another decorator which will have it's inner function decorated with the other two decorators ;)



    It might also be a good idea to use functools.wraps, for the sake of good habits. It's standard library and helps a lot with debugging and interactive console use: https://docs.python.org/3.7/library/functools.html



    In general though, I'd say the one extra line of code is more than worth the clarity of using the decorators separately. You'll thank yourself when you read your own code in 3 more months.






    share|improve this answer


















    • 1




      You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
      – Aran-Fey
      47 mins ago










    • You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
      – Jacco van Dorp
      45 mins ago










    • While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
      – bruno desthuilliers
      44 mins ago










    • If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
      – Jacco van Dorp
      41 mins ago











    • @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
      – Mad Physicist
      37 mins ago












    up vote
    6
    down vote



    accepted







    up vote
    6
    down vote



    accepted






    I would argue that you shouldn't - using the original names for the decorators gives much better readability.



    However, if you really want to, you can do it like this:



    import functools

    from moduleA import decorator1
    from moduleB import decorator2

    def my_decorator(foo, bar, name, state):
    def inner(func):
    @decorator2(foo=foo, bar=bar)
    @decorator1(name=name, state=state)
    @functools.wraps(func) # Not required, but generally considered good practice
    def newfunc(*args, **kwargs)
    return func(*args, **kwargs)
    return newfunc
    return inner

    @my_decorator(foo='param3', bar='param4', name='param1', state='param2')
    def myfunc(funcpar1, funcpar2):
    ...


    It's simple really - just write a decorator that returns another decorator which will have it's inner function decorated with the other two decorators ;)



    It might also be a good idea to use functools.wraps, for the sake of good habits. It's standard library and helps a lot with debugging and interactive console use: https://docs.python.org/3.7/library/functools.html



    In general though, I'd say the one extra line of code is more than worth the clarity of using the decorators separately. You'll thank yourself when you read your own code in 3 more months.






    share|improve this answer














    I would argue that you shouldn't - using the original names for the decorators gives much better readability.



    However, if you really want to, you can do it like this:



    import functools

    from moduleA import decorator1
    from moduleB import decorator2

    def my_decorator(foo, bar, name, state):
    def inner(func):
    @decorator2(foo=foo, bar=bar)
    @decorator1(name=name, state=state)
    @functools.wraps(func) # Not required, but generally considered good practice
    def newfunc(*args, **kwargs)
    return func(*args, **kwargs)
    return newfunc
    return inner

    @my_decorator(foo='param3', bar='param4', name='param1', state='param2')
    def myfunc(funcpar1, funcpar2):
    ...


    It's simple really - just write a decorator that returns another decorator which will have it's inner function decorated with the other two decorators ;)



    It might also be a good idea to use functools.wraps, for the sake of good habits. It's standard library and helps a lot with debugging and interactive console use: https://docs.python.org/3.7/library/functools.html



    In general though, I'd say the one extra line of code is more than worth the clarity of using the decorators separately. You'll thank yourself when you read your own code in 3 more months.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 39 mins ago









    Aran-Fey

    20.1k53065




    20.1k53065










    answered 50 mins ago









    Jacco van Dorp

    2446




    2446







    • 1




      You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
      – Aran-Fey
      47 mins ago










    • You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
      – Jacco van Dorp
      45 mins ago










    • While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
      – bruno desthuilliers
      44 mins ago










    • If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
      – Jacco van Dorp
      41 mins ago











    • @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
      – Mad Physicist
      37 mins ago












    • 1




      You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
      – Aran-Fey
      47 mins ago










    • You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
      – Jacco van Dorp
      45 mins ago










    • While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
      – bruno desthuilliers
      44 mins ago










    • If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
      – Jacco van Dorp
      41 mins ago











    • @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
      – Mad Physicist
      37 mins ago







    1




    1




    You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
    – Aran-Fey
    47 mins ago




    You should be using functools.wraps though. If you try print(myfunc) you'll get <function my_decorator.<locals>.inner.<locals>.newfunc at 0x7f5ee7bbee18> as output.
    – Aran-Fey
    47 mins ago












    You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
    – Jacco van Dorp
    45 mins ago




    You're right, of course. I was a bit in doubt because this question indicates a certain inexperience with decorators, and I wasn't sure whether to add it. I'll make an edit about it, since it's better to learn it right the first time around, though.
    – Jacco van Dorp
    45 mins ago












    While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
    – bruno desthuilliers
    44 mins ago




    While I usually agree that saving a line or two is not worth a loss in readability, if I had to apply the same two decorators to more than a couple functions I'd certainly wonder whether it's accidental or not, and in the last case refactor the whole thing to avoid repetitions.
    – bruno desthuilliers
    44 mins ago












    If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
    – Jacco van Dorp
    41 mins ago





    If they're from two different libraries, it's not accidental. @Aran-Fey: Whoops. That'll teach me from trying to edit to fast.
    – Jacco van Dorp
    41 mins ago













    @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
    – Mad Physicist
    37 mins ago




    @Jacco but then I'd start wondering why I didn't ever see the authors of the libraries in the same room at the same time.
    – Mad Physicist
    37 mins ago












    up vote
    2
    down vote













    This is just simple function composition, where decorator1 and decorator2 are returning the functions you want to compose. The real work can be abstracted out into a function compose.



    # In the special case of composing decorators, the lambda expression
    # only needs to be defined with a single argument, like
    #
    # lambda func: f(g(func))
    #
    # but I show a more general form.
    def compose(f, g):
    return lambda *args, **kwargs: f(g(*args, **kwargs))

    def customdecorator(foo, bar, name, state):
    return compose(decorator2(foo=foo, bar=bar),
    decorator1(name=name, state=state))





    share|improve this answer


























      up vote
      2
      down vote













      This is just simple function composition, where decorator1 and decorator2 are returning the functions you want to compose. The real work can be abstracted out into a function compose.



      # In the special case of composing decorators, the lambda expression
      # only needs to be defined with a single argument, like
      #
      # lambda func: f(g(func))
      #
      # but I show a more general form.
      def compose(f, g):
      return lambda *args, **kwargs: f(g(*args, **kwargs))

      def customdecorator(foo, bar, name, state):
      return compose(decorator2(foo=foo, bar=bar),
      decorator1(name=name, state=state))





      share|improve this answer
























        up vote
        2
        down vote










        up vote
        2
        down vote









        This is just simple function composition, where decorator1 and decorator2 are returning the functions you want to compose. The real work can be abstracted out into a function compose.



        # In the special case of composing decorators, the lambda expression
        # only needs to be defined with a single argument, like
        #
        # lambda func: f(g(func))
        #
        # but I show a more general form.
        def compose(f, g):
        return lambda *args, **kwargs: f(g(*args, **kwargs))

        def customdecorator(foo, bar, name, state):
        return compose(decorator2(foo=foo, bar=bar),
        decorator1(name=name, state=state))





        share|improve this answer














        This is just simple function composition, where decorator1 and decorator2 are returning the functions you want to compose. The real work can be abstracted out into a function compose.



        # In the special case of composing decorators, the lambda expression
        # only needs to be defined with a single argument, like
        #
        # lambda func: f(g(func))
        #
        # but I show a more general form.
        def compose(f, g):
        return lambda *args, **kwargs: f(g(*args, **kwargs))

        def customdecorator(foo, bar, name, state):
        return compose(decorator2(foo=foo, bar=bar),
        decorator1(name=name, state=state))






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 22 mins ago









        Aran-Fey

        20.1k53065




        20.1k53065










        answered 32 mins ago









        chepner

        230k27216313




        230k27216313




















            up vote
            0
            down vote













            Decorator is nothing more than a syntax sugar to the syntax like func = decorator(func).



            So, you can easily make your own decorator that does whatever you want with the following syntax:



            def mycustomdecorator(foo, bar, name, state)
            def innerdecorator(func):
            func = decorator1(foo=foo, bar=bar)(func)
            func = decorator2(name=name, state=state)(func)
            def wrapper(*args, **kwargs):
            func(*args, **kwargs)
            return wrapper
            return innerdecorator


            After that, you should be able to use @mycustomdecorator with no hassle. Let me know if this works, I didn't test it but theoretically it should.



            What's the magic there: first, we need to retrieve parameters for our decorators. This way, we are able to pass them on into nested function. Then, we are accepting our function as an argument, and the last, we are getting parameters for our function. We can nest our def-s as much as we need.






            share|improve this answer










            New contributor




            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.

















            • That's not quite right. You have too many nested functions there.
              – Aran-Fey
              45 mins ago










            • Can you elaborate, please?
              – Ð”митрий Клименко
              44 mins ago






            • 1




              If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
              – Aran-Fey
              42 mins ago










            • Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
              – Ð”митрий Клименко
              31 mins ago






            • 1




              (The wrong part is that wrapper should call, not return, func.)
              – chepner
              18 mins ago














            up vote
            0
            down vote













            Decorator is nothing more than a syntax sugar to the syntax like func = decorator(func).



            So, you can easily make your own decorator that does whatever you want with the following syntax:



            def mycustomdecorator(foo, bar, name, state)
            def innerdecorator(func):
            func = decorator1(foo=foo, bar=bar)(func)
            func = decorator2(name=name, state=state)(func)
            def wrapper(*args, **kwargs):
            func(*args, **kwargs)
            return wrapper
            return innerdecorator


            After that, you should be able to use @mycustomdecorator with no hassle. Let me know if this works, I didn't test it but theoretically it should.



            What's the magic there: first, we need to retrieve parameters for our decorators. This way, we are able to pass them on into nested function. Then, we are accepting our function as an argument, and the last, we are getting parameters for our function. We can nest our def-s as much as we need.






            share|improve this answer










            New contributor




            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.

















            • That's not quite right. You have too many nested functions there.
              – Aran-Fey
              45 mins ago










            • Can you elaborate, please?
              – Ð”митрий Клименко
              44 mins ago






            • 1




              If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
              – Aran-Fey
              42 mins ago










            • Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
              – Ð”митрий Клименко
              31 mins ago






            • 1




              (The wrong part is that wrapper should call, not return, func.)
              – chepner
              18 mins ago












            up vote
            0
            down vote










            up vote
            0
            down vote









            Decorator is nothing more than a syntax sugar to the syntax like func = decorator(func).



            So, you can easily make your own decorator that does whatever you want with the following syntax:



            def mycustomdecorator(foo, bar, name, state)
            def innerdecorator(func):
            func = decorator1(foo=foo, bar=bar)(func)
            func = decorator2(name=name, state=state)(func)
            def wrapper(*args, **kwargs):
            func(*args, **kwargs)
            return wrapper
            return innerdecorator


            After that, you should be able to use @mycustomdecorator with no hassle. Let me know if this works, I didn't test it but theoretically it should.



            What's the magic there: first, we need to retrieve parameters for our decorators. This way, we are able to pass them on into nested function. Then, we are accepting our function as an argument, and the last, we are getting parameters for our function. We can nest our def-s as much as we need.






            share|improve this answer










            New contributor




            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            Decorator is nothing more than a syntax sugar to the syntax like func = decorator(func).



            So, you can easily make your own decorator that does whatever you want with the following syntax:



            def mycustomdecorator(foo, bar, name, state)
            def innerdecorator(func):
            func = decorator1(foo=foo, bar=bar)(func)
            func = decorator2(name=name, state=state)(func)
            def wrapper(*args, **kwargs):
            func(*args, **kwargs)
            return wrapper
            return innerdecorator


            After that, you should be able to use @mycustomdecorator with no hassle. Let me know if this works, I didn't test it but theoretically it should.



            What's the magic there: first, we need to retrieve parameters for our decorators. This way, we are able to pass them on into nested function. Then, we are accepting our function as an argument, and the last, we are getting parameters for our function. We can nest our def-s as much as we need.







            share|improve this answer










            New contributor




            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            share|improve this answer



            share|improve this answer








            edited 10 mins ago





















            New contributor




            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            answered 49 mins ago









            Дмитрий Клименко

            394




            394




            New contributor




            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.





            New contributor





            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.






            Дмитрий Клименко is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.











            • That's not quite right. You have too many nested functions there.
              – Aran-Fey
              45 mins ago










            • Can you elaborate, please?
              – Ð”митрий Клименко
              44 mins ago






            • 1




              If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
              – Aran-Fey
              42 mins ago










            • Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
              – Ð”митрий Клименко
              31 mins ago






            • 1




              (The wrong part is that wrapper should call, not return, func.)
              – chepner
              18 mins ago
















            • That's not quite right. You have too many nested functions there.
              – Aran-Fey
              45 mins ago










            • Can you elaborate, please?
              – Ð”митрий Клименко
              44 mins ago






            • 1




              If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
              – Aran-Fey
              42 mins ago










            • Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
              – Ð”митрий Клименко
              31 mins ago






            • 1




              (The wrong part is that wrapper should call, not return, func.)
              – chepner
              18 mins ago















            That's not quite right. You have too many nested functions there.
            – Aran-Fey
            45 mins ago




            That's not quite right. You have too many nested functions there.
            – Aran-Fey
            45 mins ago












            Can you elaborate, please?
            – Ð”митрий Клименко
            44 mins ago




            Can you elaborate, please?
            – Ð”митрий Клименко
            44 mins ago




            1




            1




            If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
            – Aran-Fey
            42 mins ago




            If I have a function foo that's decorated with @mycustomdecorator(...), foo will be replaced by wrapper, which returns foo when it's called.
            – Aran-Fey
            42 mins ago












            Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
            – Ð”митрий Клименко
            31 mins ago




            Yes, I believe this is the way to preserve arguments for both foo() and mycustomdecorator(). Am I wrong?
            – Ð”митрий Клименко
            31 mins ago




            1




            1




            (The wrong part is that wrapper should call, not return, func.)
            – chepner
            18 mins ago




            (The wrong part is that wrapper should call, not return, func.)
            – chepner
            18 mins ago

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52517273%2fmerging-python-decorators-with-arguments-into-a-single-one%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            List of Gilmore Girls characters

            One-line joke