5 ms·
I'll probably get a lot of flak for this, but I find myself reaching for locals() a lot more than you'd think! It's great for prototyping, but also nice when yo
by idealmedtech 5y ago
I'll probably get a lot of flak for this, but I find myself reaching for locals() a lot more than you'd think! It's great for prototyping, but also nice when you want to generalize things like filling a data class from kwargs, then an environment variable if that didn't work, then a config file if that didn't work, then a default if that didn't work. Probably not idiomatic, but reads simply enough and pretty bulletproof, especially considering the next easiest way is something quite dangerous like eval().
Happy to be proven wrong and learn something though!
- whalesalad 5y agoI don’t necessarily want to encourage this behavior but at the same time if it works and is “pretty bulletproof” in your deployments than I’d say more power to you.
- mixmastamyk 5y agoNone of those sound like use cases for locals. Why not *kwargs for the first example?
- eesmith 5y agoCan't set default arguments with kwargs. See my example at https://news.ycombinator.com/item?id=30623987 https://news.ycombinator.com/item?id=30623987 .
- saila 5y agoI personally wouldn't let any usage of locals() through code review, except perhaps in some extremely rare circumstance. Do you have an example of "filling a data class from kwargs"?
- musingsole 5y agoConcretely, why?
- idealmedtech 5y agoA dataclass is just a class where all it does is fill internal attributes (lots of self.x = "foo"). To fill a dataclass from kwargs, instead of: def __init__(self, x=None, y=None): self.x = x self.y = y You can do: def __init__(self, **kwargs): self.__dict__.update(kwargs) # This may be **kwargs, I'm fuzzy on it With this, the following code works with both: myObj = MyClass(x=1, y=2) Now, you might say "but with the kwargs method you can add _ANY_ attribute not just x and y!" That's precisely the point. When you're still iterating on the ergonomics, you want the ability to add new things without repeating a bunch of boilerplate. Once you've figured out what those look like, you can and should go back and fix the names in stone.
- bitcoinmoney 5y agoWhat kind of style/idiom is this ? And what industry/space do you usually see this practice? Is it common? Just genuinely curious because my python is only used for scripting/pandas.
- saila 5y agoI was looking for an example of using locals() to "fill a data class from kwargs" or something similar to that. The example here doesn't use locals(). That aside, I generally wouldn't use the kwargs approach shown in this example either. I'd use https://docs.python.org/3/library/dataclasses.html https://docs.python.org/3/library/dataclasses.html or https://www.attrs.org/ https://www.attrs.org/ instead.
- wodenokoto 5y agoI’d love to see a high level example of this too, as I’m not quite sure I get the use case.
- burnished 5y agoShare a link, I'm curious
- pfranz 5y agoThis might be the flak you're expecting, but when I see locals() used in production code I've had problems refactoring it. I don't see how it's different from "from foo import *" I appreciate the terseness but looking at the code, or even with the IDE's help, I can't really see what's expected (especially if I'm looking at someone else's code). If I move things around I'll get bit at runtime--perhaps in a corner case that doesn't get caught the first time you run it. Maybe this is the use-case you're talking about, but when I have something super generic I usually have clear and careful error handling inside. It kind of defeats the terseness of using locals(), but the goal is more about flexibility.
- eesmith 5y agoHere's a locals() example from apsw: # You can use local variables as the dictionary title="..." isbn="...." cursor.execute(sql, locals()) In the pre-dataclass / pre-namedtuple days I would use: class Spam: def __init__(a=1, b=2, c=3, d="four", .. lots args ..): self.__dict__.update(locals()) del self.self in prototype code. But that wouldn't go into production. (I wouldn't put the namedtuple version in production either.)