Generics are VITAL in typed Python

แชร์
ฝัง
  • เผยแพร่เมื่อ 8 ม.ค. 2025

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

  • @thisoldproperty
    @thisoldproperty 4 หลายเดือนก่อน +27

    It's good to see advanced coding methods from time to time.

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +3

      Yeah definitely, the advanced stuff is the most fun!

    • @testaccount-b7z
      @testaccount-b7z 4 หลายเดือนก่อน +1

      Generics are fundamentals

  • @carrotmanmatt
    @carrotmanmatt 4 หลายเดือนก่อน +7

    I've used generics a couple of times, but this explanation just made it 'click' for me. Thanks for such a good video, love seeing creators put out videos for a more intermediate/advanced coding skillset.

  • @siniarskimar
    @siniarskimar 4 หลายเดือนก่อน +11

    It's funny to hear about generic types in duct-typed language like Python or JavaScript

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

    Great video! I was really surprised when I first saw generics in a library and it took me a while to wrap my head around them, especially because it's just not documented very nicely. But you did a great job explaining it!

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

    I feel people who argue that typing in Python isn’t worth the effort don’t use Python in production .

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

    I love generics!!! I personally come from Swift which is statically-types so I’m forced to use generics all the time. Hearing about them in Python was a surprise though 👍

  • @robertkalinowski6770
    @robertkalinowski6770 4 หลายเดือนก่อน +6

    About `int`, there is in builtin.pyi
    ```python
    class int:
    @overload
    def __new__(cls, x: ConvertibleToInt = ..., /) -> Self: ...
    @overload
    def __new__(cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self: ...
    class bool(int):
    def __new__(cls, o: object = ..., /) -> Self: ...
    ```
    `bool` could be built from any object (including `None` → `False`), `int` doesn't suport `None` (raises `TypeError`).
    BTW. pyright support `Box[T]`

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +3

      Yeah that's why I couldn't get it to work haha. It's also a shame Pyright isn't the defacto type checker, it's definitely far more on the ball than Mypy is.

    • @robertkalinowski6770
      @robertkalinowski6770 4 หลายเดือนก่อน +1

      @@Carberra yeah, you can use variable params length converter, eg. via Protocol.
      BTW I have a question, why do you use `C` in converter, not just `T`?
      ```python
      class Converter[T](Protocol):
      @overload
      def __call__(self) -> T: ...
      @overload
      def __call__(self, value: str, /) -> T: ...
      class EnvVar[T]:
      @overload
      def __init__(self: 'EnvVar[str|None]', name: str) -> None: ...
      @overload
      def __init__(self: 'EnvVar[str]', name: str, *, default: str) -> None: ...
      @overload
      def __init__(self, name: str, *, default: str | None = None, converter: Converter[T]) -> None: ...
      def __init__(self, name: str, *, default: str | None = None, converter: Converter[T] | None = None) -> None:
      self.name = name
      self.default = default
      self.converter = converter
      @property
      def value(self) -> T:
      value = os.environ.get(self.name, self.default)
      if self.converter is not None:
      if value is None:
      return self.converter()
      return self.converter(value)
      return cast(T, value)
      if __name__ == '__main__':
      EnvVar('FOO').value
      EnvVar('FOO', default='bar').value
      EnvVar('FOO', converter=int).value
      ```

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      C is the return type of the converter specifically. In the example, type T becomes type C, meaning that our value will be the return type of the converter. If we used T directly as you've got there, I believe you wouldn't be passing a generic type through and the type hints wouldn't work.
      I could be wrong though, try it! These types are difficult to follow sometimes, it's possible you've found a shortcut I missed.

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      Can you also elaborate on the "variable params length converter"? I'm not sure I follow.

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

      ​@@Carberra He is using a converter Class and the __call__ - Method, which defines a "own" T. By the way, you should use from __future__ import annotations. Then you can get rid of the single quotation marks in def __init__(self: 'EnvVar[str|None]', name: str) -> None: ... anyway, i a am not a pythong typing buff. Like your videos man!

  • @danielandreasen2293
    @danielandreasen2293 4 หลายเดือนก่อน +1

    I haven't seen the video yet, but it seems like just what I've been looking for. Very excited for this!

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      Hope you enjoy it!

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

    Very good example

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

    Thanks for giving a more advanced example. I did not feel like it was too difficult to follow but i do feel like i need to play around more with overloads, cause they do look cool.. Although it can make the code less readable and harder to maintain.

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

      I guess it can go both ways -- if you have an awkward type signature and need to explicitly state what's valid, they help you get a better idea of what the code can actually do.

  • @yibowei9636
    @yibowei9636 4 หลายเดือนก่อน +1

    I would love a video about the 3.12 generic syntax. Much better than subclassing Generic and using TypeVar.

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +3

      Agreed. When Mypy supports them fully I probably will come back and do that, it's a shame it's taken them this long to support it, and even now it's incomplete support.
      For now, if you're curious about it, the old and new syntaxes should both be in the GitHub repo in the description. I think I remembered to do all that.

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

    Holy boilerplate, Batman

    • @adambickford8720
      @adambickford8720 4 หลายเดือนก่อน +1

      That isn't boilerplate.

    • @Bruh-sp2bj
      @Bruh-sp2bj 4 หลายเดือนก่อน +1

      Do you know what boilerplate actually is?

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

    I'd love to see a video on ParamSpecs. I.e. how to typehint decorators

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

      I showed how to do that in my decorators video: th-cam.com/video/cG451ZXWYC4/w-d-xo.html

  • @adamdemeter6963
    @adamdemeter6963 4 หลายเดือนก่อน +1

    Nice vid
    It was easily understandable, not like the one with descriptors... Could you make an other video on that? Thanks :)

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

    This may be a stupid question...but, why the callable has to be type C, isn't it more straightforward for it to have type T? Is there some edge case where return type of converted has to be different than return type of .value()?

  • @kazukisenpai2405
    @kazukisenpai2405 6 วันที่ผ่านมา

    Does anyone have solution for 15:24 yet?

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

    You can either have strong typing or strong tests. The trick is finding the right balance

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

    I think it might because `int` do not accept `None` as input, it raise TypeError.
    So `int` conflict with `Callable[[str | None], C]`

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

    This just feel like C++ templates without the rigorous type system and more boilerplate.

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

    Which theme are you using for vscode? I really like that contrast

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      I've got a video in the description going through everything! The theme is Ayu though.

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

    Could we specify the generic type explicitly when we call a function? Like `result = my_func[T](...)`?

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

      From 3.12 yes, but Mypy doesn't support it yet. Pyright does, I believe.

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

      @@Carberra You're right I just tried it. It works in Python3.12 and VSCode Pylance!

  • @dipeshsamrawat7957
    @dipeshsamrawat7957 4 หลายเดือนก่อน +1

    Thank you 😊

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

    Would the final environ code work just as well if you were to replace the `| None`s with `Optional`?

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +3

      Yes, it'll work fine.

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

    Great video.
    Though I had a bad case of semantic satiation the nth time you said “BananaBox”.

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      Huh, that's what that phenomenon is called! And thanks!

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

    What kind of color scheme are you using? I’ve searched far and wide and haven’t got a clue. Is it a custom theme?

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

      A video talking about my setup is in the description.

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

    Python's @overload is just an annoying way to implement "real" overloads like OO languages such as Java, C# and C++ have. To write the same EnvVar class in any of those languages would be much, much easier since you can actually just write different versions of the constructor, but since Python doesn't have runtime overloads, we need to go through all that nonsense to ensure that the typing comes out right.
    Because of this, I've wanted to use @overload many times because I felt like it suited my case, but ended up doing something else because it wasn't worth it. In the EnvVar scenario, I'd probably just use different classmethods to initialise the class instead, and probably have an `identity` converter instead of a None one.

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

    Why old syntax

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

      I explained why in the video.

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

    Great

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

    "vital" is probably an exaggeration!

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

    dang ı was gonna make a video about them as well ı guess another time

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      You still can if you want! You have my blessing haha.

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

      @@Carberra thanks

  • @JOHNSMITH-ve3rq
    @JOHNSMITH-ve3rq 4 หลายเดือนก่อน

    Just not clear how one would use this in an actual project and how it’s preferable to any other particular method…. Without that it’s just very abstract and of unclear utility.

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

    At this point, why use the type system at all...? In java and csharp type parameters exist to work around the impracticalities and anoying limitations inherent to a strict type system. This completely feels like the world upside down.
    (Also why is the syntax in python soooooo extremely ugly and convoluted???)

  • @FrederikSchumacher
    @FrederikSchumacher 4 หลายเดือนก่อน +1

    Just a reminder: Python doesn't have a static type system. Python has type annotations and runtime value types. The semantics of this "static type system" is created by external non-core tools like mypy and their interpretations of the core typing module. And the typing module is second fiddle to the actual runtime value type system of the interpreter implementation. Also, since type annotations have no runtime semantics (unless you enforce it), anything you do with such type annotations serves either your own satisfaction, or serves as documentation. In the latter case is it really relevant to communicate that "kwargs: dict[str, Any]"? Since Python is interpreted, can you really achieve performance optimizations via type annotations? No you can't, because in runtime type annotations are noops. Since type annotations are noops during runtime, can you really claim correctness of code via static type checking? No you can't. So the only things Python's type annotations are useful for, is making sure your IDE developers don't have to work to hard to infer types because you're doing that job for them so diligently, and making your type documentation so specific and complex, that everyone else has to suffer through the n-th definition and alias of dict[str, any] and list[any]. Generics isn't even worth talking about, because it's just the pinnacle of the type masturbation evolution. It's literally for people that only care about the "technically correct" static representation. So if you encounter people who are deadset on going full ham with Python type annotations and static type checking, just know they're out to waste your time.

    • @virtualraider
      @virtualraider 4 หลายเดือนก่อน +3

      I'll start by acknowledging that you're absolutely right about the noop nature of the annotations. And also agree that zealotry is a waste of time. Where we diverge is in that static code analysis is useless.
      I have caught dozens of silly bugs before and after going to production when adding well-targeted type hints. The duck typing nature of python invites Devs to be liberal with variables and eventually they forget that two calls upstream a parameter can be `T | None`, which invariably leads to unhandled exceptions when people try to access methods that `None` doesn't have. That's just a common example off the top of my head.
      Others say, "then you need Go" or other statically typed language, but in enterprise we may have production systems written in python and it's non-trivial and *expensive* to rewrite, so there's definitely value in annotations, however clunky they are.

    • @FrederikSchumacher
      @FrederikSchumacher 4 หลายเดือนก่อน +1

      @@virtualraider My comment was already so long, that I didn't but should have added: You should write unit tests, probably in any language, but definitely in Python. For the amount of work you input, nothing else gives you quite the same result like unit tests do. Unit tests are runtime tests, they most definitely actually run your code.
      Any form of static code analysis can produce results, but produces results about the static nature of programs. The static nature of programs is largely irrelevant, because you must run programs to actually get results. In static time, when writing all those types, feeling good about mypy not giving warnings, you're still only dealing with an idealized fantasy of a running program.
      Static typing and static analysis is ASSUMPTIONS about a program.
      Unit tests also run in an idealized fantasy setting, but at least it runs the code. Even with the sometimes excessive mocking required in unit testing, you're still at least running the code. So unit testing, with practice around achieving branch and line coverage, will test and verify many assumptions about your code. And because unit testing tests runtime, it also tests the runtime value types. So unit testing or runtime testing will verify pretty much the same assumptions static typing makes and even a bit more.
      In all my 20+ years of programming professionally in several languages, unit tests where always the best cost-vs-benefit investment. In all my 20+ years of programming I have also learned, most developers don't actually want to run or test their programs. They like writing code but they don't like running code. Those that did run their programs, they used unit tests or other runtime tests.

    • @Carberra
      @Carberra  4 หลายเดือนก่อน +1

      Why is everyone against type annotations obsessed with comparing it to masturbation? Just euck, stop it.

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

      @@FrederikSchumacher yeah fair enough re: unit tests, I'm a huge advocate. However they serve different use cases.
      As you well pointed out, they come to play at runtime, which means you either have to be disciplined enough to run and update your tests regularly (Ideally do TDD!) or your pipeline needs to do it.
      That's late in the Dev cycle, the code is already written, possibly you're pushing a commit. OR you're new, learning, or the thing doesn't grant the effort.
      On the other hand, annotations are immediate feedback. You read it with the code, and if you use a good IDE it will tell you in real time about that code over there.
      Neither _change_ the way code works. You're exactly right it's just fantasy and idealised code. There's something else in the real world that behaves exactly like annotations:
      Traffic signs
      A stop sign doesn't actually stop your vehicle. You can drive at 80Kmh on a 40Kmh school zone and the signs are powerless against you.
      BUT that's not what they're there for. Signs are there to tell you what to do and it's up to you to follow them or face the consequences of not doing it. Same with annotations, they are there to help and prevent accidents.

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

      ​@@Carberra It's a phrase that comes from the realization how limited the usefulness of static typing in languages like Python and also TypeScript is. The most real-world practical benefit of investing into deep typing systems - like generics - is documentation. "From me the author, to you the reader and user, this is the structure of data my code is capable of handling". For readers/users, there's a threshold where the complexity of specificity surpasses the usefulness. At that point, you're no longer writing and designing the type hierarchy for anyone but yourself, you're quite literally only satisfying yourself. And satisfying only yourself and the imaginary people you think will appreciate your intense and complex type hierarchy without regard for real other people...well, that just sounds a lot like "masturbation" except without the sexual aspect of it.

  • @ali3nw0r1d6
    @ali3nw0r1d6 4 หลายเดือนก่อน +1

    Stop polluting Python!

  • @joschomo1010
    @joschomo1010 4 หลายเดือนก่อน +1

    If your using types in python maybe it's time to just use GO or something. I'm learning it now and it feels a lot like python.
    It's clunky to try and add a bunch functionality on top of a language that was never meant for it, look at js. You wind up with some grotesque monstrosity of a codebase lol

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

    PLEASE don't play background music. Between trying to understand the technical details, your accent (to my American ear) and my partial deafness, I cannot understand anything. Maybe I have ADHD and OCD also??? Just remove the "spacey" high-pitched background sounds, PLEASE!

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

    Having flashbacks to C++ templates.

  • @mudi2000a
    @mudi2000a 4 หลายเดือนก่อน +11

    This is turning Python into an abomination of a language. Worse than Java.

    • @James-the-elder
      @James-the-elder 4 หลายเดือนก่อน +9

      Typing is still optional in Python, therefore the potential abomination is optional

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

      This. Just use GO; it feels a lot like python, and it's the right tool. Stop trying to squeeze python into something it isn't, you just end up with something ugly.
      Look at js lol

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

      Well, it's mostly relevant for library developers. Just makes it easier to write good code if your editor gives you the early warning. Absolutely not needed for your own apps and scripts that are not published or used by large teams.

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

      @@Jaranvir yes I know and I admit my original comment was a bit of a clickbait comment to be honest. I think in the context of writing a library they make a lot of sense and serve also as kind of additional documentation. My personal beef is more with the syntax of the type hints which I find unnecessarily convoluted. But I also don't have a better idea how to do it.

    • @James-the-elder
      @James-the-elder 4 หลายเดือนก่อน

      @@mudi2000a have you seen Rust’s Types ?