typing decorators sucks! here's an easier way (intermediate) anthony explains

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

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

  • @philipreinhold1180
    @philipreinhold1180 5 หลายเดือนก่อน +15

    Python is easy, just use the contextmanager decorator to turn the generator into a context manager that is also at the same time a decorator factory!
    For real though i love this❤

  • @ArcRCG
    @ArcRCG 4 หลายเดือนก่อน +2

    This is cool, this decorator-context manager equivalence reflects that a decorator what basically is doing is "managing" the "context" of the wrapped function and that a context manager is basically is "decorating" an annonymous IIFE. One really beautiful abstraction.

  • @sadhlife
    @sadhlife 5 หลายเดือนก่อน +27

    wow that's a hack that I can use a lot more of

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

    I had no idea that creating a context manager like that also created a decorator. Blowing my mind, here.

  • @neonwatty
    @neonwatty 5 หลายเดือนก่อน +9

    good god man this is fantastic - thanks!

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

    Cool, didn't know you could do this. This can only be done when the decorator returns the unmodified output of the given function being called with unmodified input... correct?
    Clearly these kinds of decorators exist... like ones that register stuff, log stuff, etc... but a lot of decorators are used to modify either input, output, coerce stuff, etc.
    If this can't help in those cases the beginning of this video is actually a great reference for how to properly type regular decorators.

  • @mrswats
    @mrswats 5 หลายเดือนก่อน +50

    Excuse me, what the hell. This is super useful! Plus, much easier to test! Holy crap, I will try to remember to use this.
    Was this a planned feature? Or a coincidence by how Python is built? Or added afterwards...?

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

      yeah it got added after contextmanager was introduced

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

      @@anthonywritescode so you basically dismissed decorators and then you used decorators

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

      ???

  • @bryanbanda
    @bryanbanda 5 หลายเดือนก่อน +2

    So obvious and straightforward! Love it

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

    I don't even write python that much, randomly saw this vid in recommended. It looks amazing! Even without the fact that you don't need to type anything, it's so much nicer than defining 3 nested functions.
    Tbh python decorators are the only feature i miss in other languages, but they're so nice.

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

    That's such a nice and smart simplification, completely decoupling the function typing rather than going generic with it. Can the context manager decorator do something like logging the first parameter while also timing it, or are the parameters/return values completely out of reach?

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

      You can get access to anything with the inspect module, but things will start getting slow.

    • @anthonywritescode
      @anthonywritescode  5 หลายเดือนก่อน +2

      nope. though arguably those are need special handling anyway and I would not recommend personally

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

    There’s also the contextdecorator class that’s worth looking into

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

    Wait how you made nano like this ?? I would like to look at your dotfiles or something like this as I can't believe that nano can be like this. It's like vim or neovim but it's nicer.

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

      This isn't nano. This is babi. The gigachad here wrote it himself

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

      framing this lol. this is my editor I made github.com/asottile/babi

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

      @@anthonywritescode Wow what a crazy one. I will look at it :)

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

    Very interesting! Is this possible for concatenate introduced in PEP 612? like the one example in your previous video adding a logger

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

      this sort of intentionally prevents you from doing nasty signature mutation. the concatenate example in the other video was to demonstrate the feature and not really something I would ever do in reality

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

    How long has it been like that? Holy - soooo much easier. Is there any downside to this? Why would you ever use the "old" way? Imagine not using functools either...

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

      the only downside is no argument hackery signature modification but imo that's a good thing

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

    This is cool but what if you want override/pass the args/kwargs of the func or you want to get the name of the func?

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

      you can't, but I see that as a good thing

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

    Amazing! So all these times I've been creating context managers, I could've also used them as a decorator? 🤯

  • @ericwadebrown
    @ericwadebrown 5 หลายเดือนก่อน +2

    This is why I was sad to see verbose typing in Python. Reminds of the same thing that happened in Java. Of course, it's still optional, but still.

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

    This is incredible!

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

    Damn wish I knew this sooner. However the drawback of not accessing arguments and return values kinda limit the scope of this approach (e.g. custom caching decorator)

  • @notmymainaccount477
    @notmymainaccount477 5 หลายเดือนก่อน +2

    2:40 is there a specific reason why you use time.monotonic instead of time.perf_counter, because as far as i can remember you have always used time.monotonic in your videos?

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

      it's an alias on the platforms I care about and good enough on windows

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

      @@anthonywritescode ah i see, thanks

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

    This feels like black magic

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

    Does it make any sense if you are not into typing?

    • @anthonywritescode
      @anthonywritescode  5 หลายเดือนก่อน +2

      yes, it is still a simpler way to make decorators

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

    Is there no down sides to this?

  • @447xpro
    @447xpro 3 หลายเดือนก่อน

    Thanks!

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

    That's super smart

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

    What is the [None, None, None] typing for on the generator?

    • @philipreinhold1180
      @philipreinhold1180 5 หลายเดือนก่อน +2

      Generator has a yield type (the type in the yield), send type (usually only required for coroutines) and return type (the final returned value after the generator is exhausted)

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

      @@philipreinhold1180 thank you!

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

      th-cam.com/video/DTegfCNAXoM/w-d-xo.html for my video on the subject

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

    I just wondered if you use an IDE at work

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

      why wouldn't I use my own text editor?

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

    Anyway to generalize this to create a decorator that decorates another decorator?

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

    That's kind if new.... Contex manager working as decorator 🧐.... I need try....

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

    This is awesome, and makes for a much nicer typing experience. Quick question on the @timing_ctx example:
    is "try: finally:" really needed in this case, or just a "nice to have" for the sake of completeness?
    i.e. would the section after the "yield" be skipped on an exception inside the decorated function if we ditch the try/finally?
    I'm asking this because imho, the decorator "setup/teardown" sections would look even better/simpler/more readable without the extra indentation that the finally: block unfortunately imposes on the "teardown" section of it.
    Thanks in advance, asottile, you are a legend!

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

      yeah finally is necessary to work in the context of exceptions -- this is also true in the decorator code too (if I skipped it there it's a mistake!)

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

    Blasphemy

  • @wagneralberto5456
    @wagneralberto5456 5 หลายเดือนก่อน +2

    first!

  • @float32
    @float32 5 หลายเดือนก่อน +2

    Am I noticing correctly that the context manager method has 1000x overhead? 2ms vs the 0.002ms of the decorator!?

    • @hemerythrin
      @hemerythrin 5 หลายเดือนก่อน +7

      It's 1.7us for the decorator and 1.9us for the context manager. The 200ms one is after he added the with block containing a sleep.

    • @anthonywritescode
      @anthonywritescode  5 หลายเดือนก่อน +2

      I intentionally added a sleep so the timing output was interesting

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

      Ahh, I was just looking at the time beyond the sleep (like 0.207 at 6:19). Maybe it’s a sleep resolution thing.

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

      ah probably just python show plus vm plus recording

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

    At this you should probably go writing rust code. Easier than all this