473,289 Members | 2,087 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,289 software developers and data experts.

defaultdict.fromkeys returns a surprising defaultdict

I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:
>>b = defaultdict.fromkeys(['x', 'y'], list)
>>b
defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})
>>b['x']
<type 'list'>
>>b['z']
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
KeyError: 'z'

I think that what is really going on is that fromdict makes a regular
dictionary, and then hands it off to the defaultdict class.

I find this confusing, because now I have a defaultdict that raises a
KeyError.

Do other people find this intuitive?

Would it be better if defaultdict.fromkeys raised a
NotImplementedException?

Or would it be better to redefine how defaultdict.fromkeys works, so
that it first creates the defaultdict, and then goes through the keys?

All comments welcome. If I get some positive feedback, I'm going to try
to submit a patch.

Matt
Jun 27 '08 #1
7 3829
On Jun 3, 10:11*pm, Matthew Wilson <m...@tplus1.comwrote:
I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:

* * >>b = defaultdict.fromkeys(['x', 'y'], list)

* * >>b
* * defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})

* * >>b['x']
* * <type 'list'>

* * >>b['z']
* * ------------------------------------------------------------
* * Traceback (most recent call last):
* * * File "<ipython console>", line 1, in <module>
* * KeyError: 'z'

I think that what is really going on is that fromdict makes a regular
dictionary, and then hands it off to the defaultdict class.

I find this confusing, because now I have a defaultdict that raises a
KeyError.

Do other people find this intuitive?

Would it be better if defaultdict.fromkeys raised a
NotImplementedException?

Or would it be better to redefine how defaultdict.fromkeys works, so
that it first creates the defaultdict, and then goes through the keys?

All comments welcome. *If I get some positive feedback, I'm going to try
to submit a patch.

Matt
To me it's intuitive for it to raise a KeyError, afterall the Key
isn't in the dictionary.
Jun 27 '08 #2
On Jun 3, 9:11 pm, Matthew Wilson <m...@tplus1.comwrote:
I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:
>>b = defaultdict.fromkeys(['x', 'y'], list)
>>b
defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})
>>b['x']
<type 'list'>
>>b['z']
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
KeyError: 'z'

I think that what is really going on is that fromdict makes a regular
dictionary, and then hands it off to the defaultdict class.

I find this confusing, because now I have a defaultdict that raises a
KeyError.

Do other people find this intuitive?

Would it be better if defaultdict.fromkeys raised a
NotImplementedException?

Or would it be better to redefine how defaultdict.fromkeys works, so
that it first creates the defaultdict, and then goes through the keys?

All comments welcome. If I get some positive feedback, I'm going to try
to submit a patch.
The statement:

b = defaultdict.fromkeys(['x', 'y'], list)

is equivalent to:

b = defaultdict()
for i in ['x', 'y']:
b[i] = list

so there's no default_factory and therefore the defaultdict will
behave like a dict. Perhaps there could be an optional third argument
to provide a default_factory.
Jun 27 '08 #3
En Tue, 03 Jun 2008 17:18:59 -0300, Chris <cw****@gmail.comescribió:
On Jun 3, 10:11*pm, Matthew Wilson <m...@tplus1.comwrote:
>I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:

* * >>b = defaultdict.fromkeys(['x', 'y'], list)

* * >>b
* * defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})

* * >>b['x']
* * <type 'list'>

* * >>b['z']
* * ------------------------------------------------------------
* * Traceback (most recent call last):
* * * File "<ipython console>", line 1, in <module>
* * KeyError: 'z'

I find this confusing, because now I have a defaultdict that raises a
KeyError.
To me it's intuitive for it to raise a KeyError, afterall the Key
isn't in the dictionary.
But the idea behind a defaultdict is to *not* raise a KeyError but use the
default_factory to create missing values. (Unfortunately there is no way
to provide a default_factory when using fromkeys).

--
Gabriel Genellina

Jun 27 '08 #4
En Tue, 03 Jun 2008 17:11:06 -0300, Matthew Wilson <ma**@tplus1.com>
escribió:
I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:
>>b = defaultdict.fromkeys(['x', 'y'], list)
>>b
defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})
>>b['x']
<type 'list'>
>>b['z']
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
KeyError: 'z'

I think that what is really going on is that fromdict makes a regular
dictionary, and then hands it off to the defaultdict class.

I find this confusing, because now I have a defaultdict that raises a
KeyError.

Do other people find this intuitive?

Would it be better if defaultdict.fromkeys raised a
NotImplementedException?

Or would it be better to redefine how defaultdict.fromkeys works, so
that it first creates the defaultdict, and then goes through the keys?
That looks reasonable. It appears there is currently no way to do what you
want (apart from using a for loop to set each key)

--
Gabriel Genellina

Jun 27 '08 #5
On Jun 3, 1:11*pm, Matthew Wilson <m...@tplus1.comwrote:
I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:

* * >>b = defaultdict.fromkeys(['x', 'y'], list)

* * >>b
* * defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})

* * >>b['x']
* * <type 'list'>

* * >>b['z']
* * ------------------------------------------------------------
* * Traceback (most recent call last):
* * * File "<ipython console>", line 1, in <module>
* * KeyError: 'z'

I think that what is really going on is that fromdict makes a regular
dictionary, and then hands it off to the defaultdict class.
Nope. It works like this:

def fromkeys(iterable, value):
d = defaultdict(None)
for k in iterable:
d[k] = value
return d

Use fromkeys() to set all entries to a single specific value.
Remember that setting an entry never triggers the default factory;
instead, it is triggered on the *lookup* of a missing key. To do what
you likely intended, don't use fromkeys(). Instead write something
like:

d = defaultdict(list)
for elem in iterable:
d[elem] # factory triggered by lookup of missing key
I find this confusing, because now I have a defaultdict that raises a
KeyError.
It is only confusing because you had already convinced yourself that
the second argument in fromkeys() was the default factory function.
Of course, its real meaning is the single value assigned by fromkeys
for every insertion (the same way it works for regular dicts). Once
you realize that the second argument was the single assigned value, it
is easy to understand that the default factory function is None and
that its documented behavior is to raise a KeyError when a missing key
is looked-up.

The confusion is mostly based on a misunderstanding of how
defaultdicts work (calling a factory whenever a missing key is looked-
up, not when it is inserted). It is alo based on a misunderstanding
of what fromkeys does (assign the same value over and over for each
key in the input interable). Given those two misconceptions,
confusion over the result was inevitable.
Would it be better if defaultdict.fromkeys raised a
NotImplementedException?
No. It is a dict subclass and should provide all of those methods.
Also, it is useful in its current form.

Or would it be better to redefine how defaultdict.fromkeys works, so
that it first creates the defaultdict, and then goes through the keys?

All comments welcome. *If I get some positive feedback, I'm going to try
to submit a patch.
No need. The patch would be rejected. It would break existing code
that uses default.fromkeys() as designed and documented.
Raymond
Jun 27 '08 #6
On Jun 3, 1:11*pm, Matthew Wilson <m...@tplus1.comwrote:
I used defaultdict.fromkeys to make a new defaultdict instance, but I
was surprised by behavior:
* * >>b = defaultdict.fromkeys(['x', 'y'], list)
* * >>b
* * defaultdict(None, {'y': <type 'list'>, 'x': <type 'list'>})
One other thought: Even after correcting the code as shown in other
posts, I don't think you're on the right track. If you know the full
population of keys at the outset and just want them to all have an
initial value, the defaultdict isn't the right tool. Instead, just
populate a regular dict in usual way:
>>dict((k, []) for k in 'xyz')
{'y': [], 'x': [], 'z': []}

The time to use defaultdict is when you *don't* want to pre-populate a
dict. The factory gets run during the lookup phase and creates your
default just-in-time for use:
>>d = defaultdict(list)
for k in 'zyzygy':
d[k].append(1) # empty list created on lookup if needed
>>d
defaultdict(<type 'list'>, {'y': [1, 1, 1], 'z': [1, 1], 'g': [1]})
Raymond
Jun 27 '08 #7
>
No need. The patch would be rejected. It would break existing code
that uses default.fromkeys() as designed and documented.
Perhaps that could be useful, so that future questions or posts on the
matter could instantly be directed to the rejected patch?
Jun 27 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: James Stroud | last post by:
Hello, I want a "function factory" function in python. To do this I made a class like such (this is for Tkinter, in case your wondering): class FunctionMaker: def __init__(self, avar,...
8
by: Dan | last post by:
Hi, I did a test in C# double x1 = 1.0; double x2 = 5.29980882362664E-315; int h1 = x1.GetHashCode(); int h2 = x2.GetHashCode(); It turned out that both h1 and h2 = 1072693248
0
by: Steven Bethard | last post by:
Steven Bethard wrote: > Agreed. I really hope that Python 3.0 applies Raymond Hettinger's > suggestion "Improved default value logic for Dictionaries" from > ...
3
by: bearophileHUGS | last post by:
This post sums some things I have written in another Python newsgroup. More than 40% of the times I use defaultdict like this, to count things: .... defaultdict(<type 'int'>, {'a': 5, 'r': 2,...
45
by: charles.lobo | last post by:
Hi, I have recently begun using templates in C++ and have found it to be quite useful. However, hearing stories of code bloat and assorted problems I decided to write a couple of small programs...
3
by: Raymond Hettinger | last post by:
FWIW, here are three ways of writing constant functions for collections.defaultdict(): d = defaultdict(int) # slowest way; works only for zero d = defaultdict(lambda: 0) # faster way;...
2
by: tutufan | last post by:
It seems like x = defaultdict(defaultdict(list)) should do the obvious, but it doesn't. This seems to work y = defaultdict(lambda: defaultdict(list)) though is a bit uglier.
2
by: metaperl.com | last post by:
I'm reading http://norvig.com/spell-correct.html and do not understand the expression listed in the subject which is part of this function: def train(features): model =...
3
by: fizilla | last post by:
Hello all! I have the following weird problem and since I am new to Python I somehow cannot figure out an elegant solution. The problem reduces to the following question: How to pickle a...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.