6 ms·
I was surprised to see the example in the blog. Python actually has come pretty far with types but the blog's example doesn't really highlight it. For structura
by naddeo 2y ago
I was surprised to see the example in the blog. Python actually has come pretty far with types but the blog's example doesn't really highlight it. For structural static typing, something like this is nicer as an example
from typing import Protocol, Tuple, TypedDict
class Foo(TypedDict):
foo: str
bar: int
baz: Tuple[str, int]
baaz: Tuple[float, ...]
class Functionality(Protocol):
def do(self, it: Foo): ...
class MyFunctionality: # not explicitly implemented
def do(self, it: Foo): ...
class DoIt:
def execute(self, it: Foo, func: Functionality): ...
doit = DoIt().execute({ # Type checks
"foo": "foo",
"bar": 7,
"baz": ("str", 2),
"baaz": (1.0, 2.0)}, MyFunctionality())
Protocols and TypedDicts let you do nice structural stuff, similar typescript (though not as feature complete). Types are good enough on python that I would never consider a project without them, and I work with pandas and numpy a lot. You change your workflow a little bit so that you end up quarantining the code that interfaces with third-party libraries that don't have good type support behind your own functions that do. There are other pretty cool type things as well. Python is definitely in much better shape than it was.
Combine all of that with Pyright's ability to do more advanced type inference and its like a whole new language experience.
- bormaj 2y agoI would supplement this by suggesting `pydantic` models instead of `TypedDict`s. This library has become a core utility for me as it greatly improves the developer experience with typing/validation/serialization support.
- maleldil 2y agoThey fulfil different roles. pydantic models would be an alternative to dataclasses, attrs or data-centric classes in general. TypedDict is used when you're stuck with dicts and can't convert them to a specific class.
- catlover76 2y ago[dead]
- naddeo 2y agoYeah they're kind of different. I'm only really talking about TypedDicts because the original post was related to structural typing, which isn't what pydantic does. I do reach for pydantic first myself.
- oivey 2y agoTypedDicts are a really disappointing feature. Typing fails if you pass it a dictionary with extra keys, so you can’t use it for many structural typing use cases. It’s even more disappointing because this isn’t just an oversight. The authors have deliberately made having additional keys an error. Apparently, this even a divergence from how TypeScript checks dictionaries.
- Syntaf 2y agoFor what it's worth, TypedDict was a bit ahead of it's own time. Python 3.12 is really the turning point for being able to leverage them effectively for stuff like **kwargs[1][2] from typing import TypedDict, Unpack, NotRequired class Movie(TypedDict): name: str year: NotRequired[int] def foo(**kwargs: Unpack[Movie]) -> None: ... [1] https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-kwargs https://typing.readthedocs.io/en/latest/spec/callables.html#... [2] https://peps.python.org/pep-0692/ https://peps.python.org/pep-0692/
- o11c 2y agoHow does that work for partial forwarding? Back when I last checked there was no imagining a DRY solution for that even for linear cases, let alone diamond inheritance. # Simple case, any halfway-decent type system should be able to handle this. def inner(*, i): pass def middle(*, m, **kwargs): inner(**kwargs) def outer(*, o, **kwargs): middle(**kwargs) kwargs = ...; outer(**kwargs) # More complicated case, but fairly common in Python code. class A: def __init__(self, *, a): pass class B(A): def __init__(self, *, b, **kwargs): super().__init__(**kwargs) class C(A): def __init__(self, *, c, **kwargs): super().__init__(**kwargs) class D(B, C): def __init__(self, *, d, **kwargs): super().__init__(**kwargs) kwargs = ...; D(**kwargs) # An even more complicated case involves `kwargs.pop()`, forwarding without `**`. Can the above be typechecked yet?
- o11c 2y agoTo be fair, that behavior on typescript's part is a major hole for bugs to slip through. Specifically: absent optional keys + extra keys is fundamentally indistinguishable from miseptl keys.