Issue 23372: defaultdict.fromkeys should accept a callable factory (original) (raw)
Issue23372
Created on 2015-02-01 16:19 by justanr, last changed 2022-04-11 14:58 by admin. This issue is now closed.
Messages (9) | ||
---|---|---|
msg235180 - (view) | Author: Alec Nikolas Reiter (justanr) | Date: 2015-02-01 16:19 |
Not something I've noticed until today, but defaultdict.fromkeys only accepts an iterable of keys and an initial value. To set the default_factory for the newly created collection, you need to prod at the attribute itself. This isn't a huge issue for me, however adding an optional default_factory to fromkeys would be a nice convenience. | ||
msg235181 - (view) | Author: SilentGhost (SilentGhost) * ![]() |
Date: 2015-02-01 16:47 |
Correct me if I'm wrong but this seem as a very unlikely use case. Why would you need to ensure content of the defaultdict (i.e., why would you ever use its fromkeys method)? And, perhaps, having to implicitly assign default factory is not such a bad tradeoff, considering implementation overhead. | ||
msg235187 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2015-02-01 18:00 |
-0 I could see some use cases for this, dict.fromkeys(contestants, factory=list), but it adds complexity to a core container API and it starts to overlap the use cases for collections.defaultdict(). Perhaps set comprehensions should remain the one-obvious-way-to-do-it: {k : [] for k in contestants} | ||
msg235191 - (view) | Author: SilentGhost (SilentGhost) * ![]() |
Date: 2015-02-01 18:27 |
Raymond, but Alec talks about defaultdict.fromkeys(constants, factory=list) as opposed to current solution d = defaultdict.fromkeys(constants) d.default_factory = list for i in d: d[i] = [] I wouldn't think that the dict.fromkeys should be affected by this issue. | ||
msg235193 - (view) | Author: Alec Nikolas Reiter (justanr) | Date: 2015-02-01 18:38 |
@SilentGhost I was playing with a voting algorithm (Instant Runoff, rather than traditional majority). Ultimately, I ended up using Counter in place of a defaultdict, but that's how I ended up noticing it. Not so much ensuring the content so much as setting an initial default state to mutate. @rhettinger I had considered a comprehension and passing it into a defaultdict (or Counter) to get that nice missing key handling. Implicitly assigning the factory is a pretty good compromise, like I said fromkeys accepting the factory would be a nice convenience rather than correcting a major oversight. | ||
msg235196 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2015-02-01 18:53 |
It may be written simpler: d = defaultdict(factory) for i in constants: d[i] or d = defaultdict(factory, {i: factory() for i in constants}) I'm inclined to reject this proposition. It serves very special use case. | ||
msg276981 - (view) | Author: Gavin Panella (allenap) | Date: 2016-09-19 15:48 |
It's inconsistent that defaultdict([]) should be rejected: >>> defaultdict([]) Traceback (most recent call last): File "", line 1, in TypeError: first argument must be callable or None but defaultdict.fromkeys([]) is okay: >>> defaultdict.fromkeys([]) defaultdict(None, {}) The constructor signature differs between defaultdict and dict, and defaultdict.fromkeys is an alternate constructor, so it seems reasonable to also change its signature. Also confusing is that I can call fromkeys on an instance of defaultdict: >>> dd = defaultdict(list) >>> dd.fromkeys([1]) defaultdict(None, {1: None}) Instinctively I expect the default_factory to be carried over, even though I realise that would be odd behaviour for Python. If defaultdict.fromkeys were to expect a mandatory default_factory argument there wouldn't be this moment of confusion. | ||
msg276997 - (view) | Author: Vedran Čačić (veky) * | Date: 2016-09-20 01:42 |
That's usual behavior for any class method. You can call them on an instance, but they don't have the access to it, only to its class. So transferring of factory would in fact not be possible. Of course,it's possible to make fromkeys an instance method, but please don't do that. | ||
msg277000 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2016-09-20 03:39 |
[Serhiy] I'm inclined to reject this proposition. It serves very special use case. [Silent Ghost] Correct me if I'm wrong but this seem as a very unlikely use case [Alec Nikolas Reiter] Implicitly assigning the factory is a pretty good compromise, like I said fromkeys accepting the factory would be a nice convenience rather than correcting a major oversight. ----- After thinking about the above, I'm disinclined to make the API modification. The current way to do it is straight-forward and reads nicely: >>> d = defaultdict.fromkeys('abcdefg', somedefault) >>> d.default_factory = somefunc Combining those into a single step is less readable and may incorrectly imply some sort of interaction between the factory function and initial population of keys with a constant default value. Likewise, the possibility of implicitly guessing and assigning the factory function is contraindicated by the zen-of-python in at least two places. Given the paucity of use cases, the potential for API confusion, and the ready availability of reasonable alternatives, I'm closing the feature request. Thank for the suggestion though, it certainly seemed like something that deserved a little more thought. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:58:12 | admin | set | github: 67561 |
2016-09-20 03:39:26 | rhettinger | set | status: open -> closedresolution: rejectedmessages: + |
2016-09-20 01:42:08 | veky | set | nosy: + vekymessages: + |
2016-09-19 15:48:05 | allenap | set | nosy: + allenapmessages: + |
2015-02-01 18:53:22 | serhiy.storchaka | set | nosy: + serhiy.storchakamessages: + |
2015-02-01 18:38:31 | justanr | set | messages: + |
2015-02-01 18:27:01 | SilentGhost | set | messages: + |
2015-02-01 18:00:06 | rhettinger | set | assignee: rhettingermessages: + |
2015-02-01 17:33:48 | serhiy.storchaka | set | nosy: + rhettinger |
2015-02-01 16:47:15 | SilentGhost | set | versions: - Python 3.4nosy: + SilentGhostmessages: + components: + Library (Lib) |
2015-02-01 16:19:44 | justanr | create |