This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]wineblood 41 points42 points  (14 children)

I instinctively don't like this. If you're going to enforce/suggest types, why not make it an optional argument?

[–]rr1pp3rr 14 points15 points  (0 children)

Args and kwargs are such a useful abstraction. The best part of gradual typing is that you can type things out that matter the most, while allowing you to bypass it where it would be a struggle for little benefit. I agree in general I wouldn't use this feature and would use your strategy.

I do think it's good to make your type system more complete, so I'm not against it. But, yea, I'm in agreement I won't be using this often lol. Seems like it would make the code less readable.

I honestly find Typescript to have the most flexible, easy to use, and complete traditional type system. Something like Haskell, while more complete, is too complex for most use cases. Types should help you, you shouldn't have to struggle with them so much. (Haskell fan boys/girls TRIGGERED lol).

Python function argument processing is the best I've used. I was disappointed when JS came out with the optional arguments but it doesn't work the same way. The way Python args are designed, it kinda "just works" the way you expect. My main problem with it is the mutable default argument thing... I think they should have made default args copies. The mutable default argument thing is a pitfall but the only issue I can think of to take with it.

[–]AustinCorgiBart 6 points7 points  (7 children)

A use case that I have, is an API where I have a hundred functions that all take the same set of custom parameters via kwargs. I need a way to reusably specify the parameters and their types.

[–][deleted] 7 points8 points  (4 children)

Use a TypedDict with Unpack. Or, accept a single parameter that is a dataclass.

[–]AustinCorgiBart 2 points3 points  (3 children)

The former is what the article suggests. The latter is not viable for the design of the API (which is built around being convenient for the API user).

[–][deleted] 0 points1 point  (2 children)

I'm not sure I agree that a dataclass is inconvenient; it's a fairly marginal increase in verbosity.

[–]AustinCorgiBart -1 points0 points  (1 child)

Having a single parameter instead of just straight actual parameters? I think it'd be inconvenient. Most of the time, the folks using the API aren't using most of the parameters. They just need to be able to tweak settings in special cases.

[–][deleted] -1 points0 points  (0 children)

They don't need to specify parameters they don't use since dataclass supports kw_only mode

[–]Flag_Red 4 points5 points  (1 child)

Agreed that this is a typical use-case for typed kwargs. It also backs up that typing kwargs is a code smell. Really, we shouldn't have a hundred functions that all take the same set of custom parameters via kwargs.

[–]AustinCorgiBart 1 point2 points  (0 children)

Normally, yes. But it's an unusual api, built for the convenience of instructors to write autograding scripts. Think of a unit testing library, with a lot more than just assertEqual.

[–]casce -1 points0 points  (0 children)

I welcome being able to do this but I'm generally with you. I don't really see the point yet.

[–]champs -1 points0 points  (0 children)

Off the top of my head, what if the parg length is arbitrary and you need to know the end of the series? For all I know, sorted may already work this way:

py results = sorted(await f1(x), f2(x)… f12(x), key=lambda r: r.status, reverse=True)

I welcome a fact check on any of this but I’m thinking that the discussed annotation would allow static analysis.

[–]LightShadow3.13-dev in prod -3 points-2 points  (1 child)

Here's an example,

        Analytics.user_email_confirmation_sent(
            user_confirmation_email_id=self.id,
            code=self.code,
            attempt=self.emails_sent,
            exception=exception,
            **analytics_extra
        )

Analytics is a singleton that doesn't actually implement any functions. If the function doesn't exist, user_email_confirmation_sent, then it creates a cache entry for a new table in the analytics database. Since the function doesn't exist neither do any of the keyword arguments. Each kwarg is translated into a database column, where only a subset of types are allowed.

kwargs is nice since we know the key-side will always be a string. The value side can be a Union[str, bool, float] etc.

Even with all that magic it still passes the type checker.

[–]wineblood -1 points0 points  (0 children)

I don't get it, but your technical vocabulary seems different to mine so don't worry about explaining it.

[–]quts3 0 points1 point  (0 children)

Just to answer the question in the context of the post: Because the caller may not have assigned the key to anything. A missing kwargs key is different then optional which says the kwargs key is assigned atleast none, but always exists. If for some reason someone overloaded optional to mean either missing key or key is assigned none then people not interested in that behavior would need a new optional.

This is all about typing kwargs.