3 ms·
Better than both use Pydantic. You'll never want to use anything else ever again. It's truly transformative in how you write code. Full type hinting support as
by Spivak 2y ago
Better than both use Pydantic. You'll never want to use anything else ever again. It's truly transformative in how you write code. Full type hinting support as well as strong verification that your data actually conforms to the types you set. Full recursive parsing of types arbitrarily nested and can parse tagged and untagged unions.
- serjester 2y agoTypedDicts are enormously helpful in defining args a function takes. You can’t do that with either dataclasses / pydantic without passing instantiated objects as args - which is really cumbersome.
- Spivak 2y agoI actually have a function for this! I use it all the time and it's super helpful. T = TypeVar("T") U = TypeVar("U") V = TypeVar("V") P = ParamSpec("P") def modelargs(model: Callable[P, U]): def _modelargs(func: Callable[[T], V]) -> Callable[P, V]: def __modelargs(*args: P.args, **kwargs: P.kwargs) -> V: return func(model(*args, **kwargs)) # type: ignore return __modelargs # type: ignore return _modelargs class MyModel(BaseModel): foo: str bar: int = 4 @modelargs(MyModel) def test_func(model: MyModel): print(model.foo, model.bar) return 4 test_func(foo="Hello", bar=20) # -> prints Hello 20 If you look in your editor you'll see that the type signature for test_func is `(*, foo: str, bar: int = 4) -> int`. It's unfortunate that you have to write the model type twice but in exchange you don't have to write the args twice.
- rattray 2y agoInteresting! How does that work for nested properties?
- FreakLegion 2y agoI think serjester was talking about PEP 692 for typing kwargs with TypedDicts. Your recipe is a bit different. Pydantic is targeting other use cases. The point of TypedDicts is compile-time safety without run-time overhead. Pydantic is useful for a lot of things, but performance isn't exactly its strong suit (written as of 2.9.2, I was just revisiting it earlier this week). Anyway, in the same spirit of function signature hacking, I've found the following useful for "inheriting" them: _T = TypeVar("_T", bound=Callable) def inherit_signature(_function: _T) -> Callable[..., _T]: return lambda f: f # Requests for example has some long signatures (via typeshed). class CustomSession(requests.Session): @inherit_signature(requests.Session.post) def post(self, url: str, *args: Any, **kwargs: Any) -> requests.Response: ... And now for CustomSession.post the editor sees: def post( self: Session, url: str | bytes, data: _Data | None = None, json: Any | None = None, *, params: _Params | None = ..., headers: _HeadersUpdateMapping | None = ..., cookies: RequestsCookieJar | _TextMapping | None = ..., files: _Files | None = ..., auth: _Auth | None = ..., timeout: _Timeout | None = ..., allow_redirects: bool = ..., proxies: _TextMapping | None = ..., hooks: _HooksInput | None = ..., stream: bool | None = ..., verify: _Verify | None = ..., cert: _Cert | None = ... ) -> Response
- darkteflon 2y agoReally like Pydantic - assuming you’re happy to step outside the standard library. It does have a few sharp edges, but out of the box it includes all the stuff you eventually end up needing anyway. attrs is the other big Python parsing / validation library. I know nothing about it other than it’s also popular and that it distinguishes itself philosophically from Pydantic in a number of ways. Don’t forget to use ‘ConfigDict(frozen=True)’ absolutely everywhere!
- richrichie 2y agoI looked up the docs as to what frozen does: > whether or not models are faux-immutable, i.e. whether __setattr__ is allowed (default: True) Seems everything is “faux” in Python world when it comes to typing ;)
- stavros 2y agoUnfortunately I can't downvote, but this comment is just flamebait.
- richrichie 2y agoAh, sensitive type you are! Read my reply above.
- Spivak 2y agoPython very much lives up to its goal of being a language for consenting adults. It's part of the culture that you don't write code that tries to forbid users of your code from doing "wrong" things and such efforts are mostly futile anyway. You can reach right into a Python object's internal data and modify it directly, taking away __setattr__ is just a suggestion. It's the same as in C where you can modify const variables if you're determined enough.
- richrichie 2y agoI love Python and use it extensively. I just find the extensive typing rituals a bit funny. If one needs this much bandaid (essentially for code editors), then Python is not a good choice for the task.
- neeleshs 2y agoThe author touches upon why typeddicts with total=False are more ergonomic than Pydantic for the examples they have.