5 ms·
The ability of **kwargs to leave behind no proper documentation and silently swallow any invalid arguments has made us remove them entirely from our codebase. T
by refactor_master 3y ago
The ability of **kwargs to leave behind no proper documentation and silently swallow any invalid arguments has made us remove them entirely from our codebase. They're almost entirely redundant when you have dataclasses.
- liquidpele 3y agoYea, really only useful imho for proxy functions that then just pass the arguments along to something that DOES properly type every arg.
- roland35 3y agoI agree - it is convenient to use at first but it sure makes it hard to use an unfamiliar codebase!
- zbentley 3y agoWhat about decorators, or wrappers around third-party code whose contracts change frequently (or even second party code when interacting with functions provided by teams that don't follow explicit argument typing guidelines, if you have that sort of culture)?
- refactor_master 3y agoUsually the solutions range from a culture of “just don’t” to tests/mypy that have become increasingly stricter over the years, every time we’ve come a step further up the ladder. But I admit, it has taken quite some bridging to get there. Moving to static Python in most places has dramatically improved the code and language.
- plonk 3y agoThose are better handled by typing.ParamSpec, it should keep track of the unwrapped function's arguments.
- jerpint 3y agoWhat do you do when inheriting from a base class with a defined __init__ ?
- yayachiken 3y agoFor everybody reading this and scratching their head why this is relevant: Python subclassing is strange. Essentially super().__init__() will resolve to a statically unknowable class at run-time because super() refers to the next class in the MRO. Knowing what class you will call is essentially unknowable as soon as you accept that either your provider class hierarchy may change or you have consumers you do not control. And probably even worse, you aren't even guaranteed that the class calling your constructor will be one of your subclasses. Which is why for example super().__init__() is pretty much mandatory to have as soon as you expect that your class will be inherited from. That applies even if your class inherits only from object, which has an __init__() that is guaranteed to be a nop. Because you may not even be calling object.__init__() but rather some sibling. So the easiest way to solve this is: Declare everything you need as keyword argument, but then only give **kwargs in your function signature to allow your __init__() to handle any set of arguments your children or siblings may throw at you. Then remove all of "your" arguments via kwargs.pop('argname') before calling super().__init__() in case your parent or uncle does not use this kwargs trick and would complain about unknown arguments. Only then pass on the cleaned kwargs to your MRO foster parent. So while using **kwargs seems kind of lazy, there is good arguments, why you cannot completely avoid it in all codebases without major rework to pre-existing class hierarchies. For the obvious question "Why on earth?" These semantics allow us to resolve diamond dependencies without forcing the user to use interfaces or traits or throwing runtime errors as soon as something does not resolve cleanly (which would all not fit well into the Python typing philosophy.)
- sbrother 3y agoThank you for explaining this; there are a lot of comments here suggesting trivial code style improvements for use cases where *kwargs wasn’t actually needed. The more interesting question is how to improve the use case you describe — which is how I’ve usually seen *kwargs used.
- deleted 3y ago[deleted]
- hooloovoo_zoo 3y agoSeems pretty important for something like a plotting function where you want to be able to pass any tweaks to any subplots.
- codexb 3y agoThey are a necessity for subclasses though, especially when subclassing from an external library that will likely change underneath you.
- EdwardDiego 3y ago/me cries in Django Kwargs everywhere, often only defined for a type at runtime by spooky voodoo action at a distance metaclass shenanigans...
- jtdev 3y ago[dead]
- systemvoltage 3y agoHello, I am pytest. I heard ya'll are talking about magic and kwargs fudging?