How To Make A Simple Function Decorator (Python Recipes)

แชร์
ฝัง
  • เผยแพร่เมื่อ 23 ธ.ค. 2024

ความคิดเห็น • 41

  • @aaronvegoda1907
    @aaronvegoda1907 5 หลายเดือนก่อน +20

    For anyone wondering how to fully type hint a decorator, here it is.
    import functools
    from typing import Callable, ParamSpec, TypeVar
    P = ParamSpec("P")
    T = TypeVar("T")
    def time_func(func: Callable[P, T]) -> Callable[P, T]:
    @functools.wraps(func)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
    # code
    result = func(*args, **kwargs)
    # code
    return result
    return wrapper
    What ParamSpec does, is it captures not only the exact signature of the callable, but the names of the args as well.

    • @ApprendreSansNecessite
      @ApprendreSansNecessite 5 หลายเดือนก่อน

      Amazing! You even get the parameter *names* and not only their types That's the way to do it

    • @JorjaRebeca-qw8tv
      @JorjaRebeca-qw8tv 5 หลายเดือนก่อน

      Sorry

  • @therealslimaddy
    @therealslimaddy 5 หลายเดือนก่อน +1

    Functools wraps solved my biggest problem(I was trying to apply two decorators).
    Thanks for this!!

  • @fire17102
    @fire17102 5 หลายเดือนก่อน +10

    Is there a decorator that makes a functuon async? Without infecting all the functions that call it to be async aswell? Thanks

    • @largewallofbeans9812
      @largewallofbeans9812 5 หลายเดือนก่อน +8

      Making a function async intrinsically requires functions that await it to be async as well. To run an async function without awaiting it, use `asyncio.run(function())`, where "function" is your async function.

    • @fire17102
      @fire17102 5 หลายเดือนก่อน +3

      @@largewallofbeans9812 thanks! Though still wondering if there's a asyncio decorator that does that automatically

    • @_Blazing_Inferno_
      @_Blazing_Inferno_ 5 หลายเดือนก่อน +1

      Is there a way of telling from function 2 whether function 1 (which calls function 2) is async? If there is, you might be able to make your own where the wrapper could call async.run(function2()) if function 1 is not async, but if function 1 is async, the wrapper can just call function 2 normally.
      If there isn’t such a thing you might still be able to make a wrapper like `wrapper(is_async: bool, *args, **kwargs)` which then calls function2(*args, **kwargs) or async.run(function2(*args, **kwargs)) based on what is_async is (which function 1 would have to directly supply).
      I haven’t messed with async/await yet and haven’t successfully found how to check stuff about caller functions from callee functions, though, so I might be misunderstanding how these things work

    • @Jason-b9t
      @Jason-b9t 5 หลายเดือนก่อน

      ​@@_Blazing_Inferno_This doesn't make sense because you can't nest asyncio.run(), nor should you await arbitrary async functions.
      In order to make asynchronous execution truly asynchronous, you need asyncio.create_task() to start the task, then await asyncio.gather() to collect the results, handle timeout errors, etc. The entire asynchronous program code is actually much different from the synchronous program.

    • @mishasawangwan6652
      @mishasawangwan6652 5 หลายเดือนก่อน

      you can simply wrap the function in `ensure_future` (which would return an awaitable).
      also check out `.run_in_executor()` method for related functionality.

  • @obsidiansiriusblackheart
    @obsidiansiriusblackheart 5 หลายเดือนก่อน +1

    You should do a pytest video using conftest and show how to mock a wrapped method (I did this recently at work, I'm a senior dev and it certainly wasn't easy just using docs/copilot lol)

  • @ranjithkumars2398
    @ranjithkumars2398 5 หลายเดือนก่อน

    I always have a confusion with decorators, Thanks for this video❤
    I cannot quite understand the super function can please explain it in the next video

  • @QBitDevs
    @QBitDevs 5 หลายเดือนก่อน

    Great video, learned a lot

  • @dipeshsamrawat7957
    @dipeshsamrawat7957 5 หลายเดือนก่อน

    Thank you.

  • @danbromberg
    @danbromberg 5 หลายเดือนก่อน

    Good video but it'd be helpful if you either briefly summarized what a 'decorator' does or pointed to one of your earlier videos that discussed it.

    • @dereknirenbergmusic
      @dereknirenbergmusic 5 หลายเดือนก่อน

      The important thing is the first function, in this video "get_time." Notice that instead of taking variables as an input it takes a function. Adding @get_time as a decorator to "calculate" basically says "send this function through the 'get_time' function." Notice that in the "get_time" function, line 12 of code is what actually runs the "calculate" function.
      So the decorator is telling Python to send the function it's decorating through the decorator function.

  • @at0m1x191919
    @at0m1x191919 5 หลายเดือนก่อน

    awesome!

  • @cocoatea57
    @cocoatea57 5 หลายเดือนก่อน

    Thanks for this

  • @anon_y_mousse
    @anon_y_mousse 5 หลายเดือนก่อน

    And here I was thinking a decorator in Python was a feather boa. ;)

  • @celestialowl8865
    @celestialowl8865 5 หลายเดือนก่อน

    Lambda and nested lambda decorators are novel but neat

    • @DrDeuteron
      @DrDeuteron 5 หลายเดือนก่อน +1

      the point of a decorator is reuse code...and lambdas don't do that.

    • @celestialowl8865
      @celestialowl8865 5 หลายเดือนก่อน

      @@DrDeuteron Lambda decorators enable IIFEs in python, but as stated the application is less generally applicable and more just a good tool to have in your toolkit. I use it for debugging on occasion

    • @ApprendreSansNecessite
      @ApprendreSansNecessite 5 หลายเดือนก่อน +1

      @@celestialowl8865 lambdas have nothing to do with IIFE. You can define an IIFE with a named decorator. And it's not an IIFE anyway because it's not an expression

    • @celestialowl8865
      @celestialowl8865 5 หลายเดือนก่อน

      @@ApprendreSansNecessite I should have specified that they allow for a cleaner standard format*. Obviously anything performed by a lambda can be directly reproduced by a named decorator.

    • @ApprendreSansNecessite
      @ApprendreSansNecessite 5 หลายเดือนก่อน +1

      ​@@celestialowl8865 I totally understand your hype for lambdas but they are half-backed. Most of the use cases I have for them in other languages can't be expressed in (typed) Python

  • @aguy98ptk
    @aguy98ptk 5 หลายเดือนก่อน

    nice

  • @looploop6612
    @looploop6612 5 หลายเดือนก่อน

    what if func has a return value ?

  • @rishiraj2548
    @rishiraj2548 5 หลายเดือนก่อน

    Good day greetings

  • @duWud
    @duWud 5 หลายเดือนก่อน

    what code editor are you using?

    • @milara69
      @milara69 5 หลายเดือนก่อน

      pycharm

  • @TristanM971
    @TristanM971 5 หลายเดือนก่อน

    I heard also about decorators with parameters, but the way it's implemented looks dirty to me, so i prefer using functions composition/currying instead of decorators when it becomes more complex.

  • @kundan.072
    @kundan.072 5 หลายเดือนก่อน

    May someone tell me that which app is this?

  • @QBitDevs
    @QBitDevs 5 หลายเดือนก่อน

    First!

  • @ApprendreSansNecessite
    @ApprendreSansNecessite 5 หลายเดือนก่อน

    If you do this you totally loose the type signature of your function. It becomes `(...) -> Any`

  • @tinkuabraham9653
    @tinkuabraham9653 5 หลายเดือนก่อน

    which IDE is this?

  • @DrDeuteron
    @DrDeuteron 5 หลายเดือนก่อน

    I read a decorator is a macro, but it's written in python.

    • @ApprendreSansNecessite
      @ApprendreSansNecessite 5 หลายเดือนก่อน +1

      It is not a macro, it is a higher order function. It is equivalent to writing `def _fn(x, y): ...; fn = decorator(__fn)` or `fn = decorator(lamda x, y: ... )`. The difference is that you pay the price of this abstraction every time you call `fn` whereas a macro would be executed either at compile time or during an initial macro expansion phase.
      When you use higher order functions, functions are data, but when you use macros, *code* is data