I am getting an error saying "dict_key object does not support indexing" at:
return len(G[G.keys()[0]])
I realised it used to work in python 2.7.x but not in python 3.How should i change this statement to make it work in python 3.
In Python 2.x, G.keys() returns a list, but Python 3.x returns a dict_keys object instead. The solution is to wrap G.keys() with call to list(), to convert it into the correct type:
return len(G[list(G.keys())[0]])
In Python 3, the objects returned by keys, values, and items are dictionary view objects, which don't support indexing.
Try, instead:
len(next(iter(G.values())))
This gets the dictionary view object for the dictionary's values, gets its iterator, grabs the first item from the iterator (the first value in the dictionary), and returns its length.
Unlike other methods that create a new list of the keys or values, it should take approximately the same amount of time no matter the size of the dictionary.
It works in both Python 2 and Python 3 (though to be efficient you'd need to use itervalues or viewvalues on Python 2).
Related
I want to change a Python 2 code to Python 3. In particular, I would like to change a.itervalues to a.values.
I would to know if it is possible to define a new function so that when the program comes across .itervalues, it will run my new function instead of its original one?
Thank you very much.
as #aws_apprentice said : go to https://docs.python.org/3/library/2to3.html
specifically read this section :
dict Fixes dictionary iteration methods. dict.iteritems() is converted
to dict.items(), dict.iterkeys() to dict.keys(), and dict.itervalues()
to dict.values(). Similarly, dict.viewitems(), dict.viewkeys() and
dict.viewvalues() are converted respectively to dict.items(),
dict.keys() and dict.values(). It also wraps existing usages of
dict.items(), dict.keys(), and dict.values() in a call to list.
so all you need to do is run 2to3 script on your files and you customize your code to suit Python 3 convention.
What's the asymptotic complexity of dict.keys() in python?
I found this website but it does not have the answer. I am using Python 3, but I guess this is not version specific.
In Python 3, dict.keys() returns a view object. Essentially, this is just a window directly onto the dictionary's keys. There is no looping over the hashtable to build a new object, for example. This makes calling it a constant-time, that is O(1), operation.
View objects for dictionaries are implemented starting here; the creation of new view objects uses dictview_new. All that this function does is create the new object that points back at the dictionary and increase reference counts (for garbage tracking).
In Python 2, dict.keys() returns a list object. To create this new list, Python must loop over the hashtable, putting the dictionary's keys into the list. This is implemented as the function dict_keys. The time complexity here is linear with the size of the dictionary, that is O(n), since every slot in the table must be visited.
N.B. dict.viewkeys() in Python 2 does the same as dict.keys() in Python 3.
First of all I am new to Python. I am using PTVS http://pytools.codeplex.com/. Next I installed reportlab. Then I run a sample demo at https://github.com/nakagami/reportlab/blob/master/demos/colors/colortest.py#L68 But at line,
all_colors = reportlab.lib.colors.getAllNamedColors().items()
all_colors.sort() # alpha order by name
I am getting error, dict_items object has no attribute sort
Haven't tested but a theory: you are using python3!
From https://docs.python.org/3/whatsnew/3.0.html
dict methods dict.keys(), dict.items() and dict.values() return “views” instead of lists. For example, this no longer works: k = d.keys(); k.sort(). Use k = sorted(d) instead (this works in Python 2.5 too and is just as efficient).
as I understand it a "view" is an iterator, and an iterator does not have the sort function. Change it to
sorted(all_colors)
according to the documentation
So the total solution based on Johan's answer is:
all_colors = sorted(reportlab.lib.colors.getAllNamedColors().items())
I believe the sort() method doesn't support Python 3.x anymore.
It is necessary to pass the corresponding variable to the sorted(all_colors).
I'm looking at an output from 2to3 that includes this change:
- for file_prefix in output.keys():
+ for file_prefix in list(output.keys()):
where output is a dictionary.
What is the significance of this change? Why does 2to3 do this?
How does this change make the code Python 3 compatible?
In Python 3, the .keys() method returns a view object rather than a list, for efficiency's sake.
In the iteration case, this doesn't actually matter, but where it would matter is if you were doing something like foo.keys()[0] - you can't index a view. Thus, 2to3 always adds an explicit list conversion to make sure that any potential indexing doesn't break.
You can manually remove the list() call anywhere that a view would work fine; 2to3 just isn't smart enough to tell which case is which.
(Note that the 2.x version could call iterkeys() instead, since it's not indexing.)
In Python 2.x, dict.keys() returns a list.
In Python 3.x, dict.keys() returns a view and must be passed to list() in order to make it a list.
Since the Python 2.x code doesn't need a list it should call dict.iterkeys() instead.
In Python 2, .keys() returns a list of the keys, but in Python 3 it returns a non-list iterator. Since 2to3 can't know whether you really needed the keys to be a list, it has to err on the side of caution and wrap the call in list so you really get a list.
In Python2, keys returned a list while in 3 the return of keys is a dict_keys object. So if you were dependent on the list-result behavior, the explicit conversion is necessary.
I recently wrote some code that looked something like this:
# dct is a dictionary
if "key" in dct.keys():
However, I later found that I could achieve the same results with:
if "key" in dct:
This discovery got me thinking and I began to run some tests to see if there could be a scenario when I must use the keys method of a dictionary. My conclusion however is no, there is not.
If I want the keys in a list, I can do:
keys_list = list(dct)
If I want to iterate over the keys, I can do:
for key in dct:
...
Lastly, if I want to test if a key is in dct, I can use in as I did above.
Summed up, my question is: am I missing something? Could there ever be a scenario where I must use the keys method?...or is it simply a leftover method from an earlier installation of Python that should be ignored?
On Python 3, use dct.keys() to get a dictionary view object, which lets you do set operations on just the keys:
>>> for sharedkey in dct1.keys() & dct2.keys(): # intersection of two dictionaries
... print(dct1[sharedkey], dct2[sharedkey])
In Python 2.7, you'd use dct.viewkeys() for that.
In Python 2, dct.keys() returns a list, a copy of the keys in the dictionary. This can be passed around an a separate object that can be manipulated in its own right, including removing elements without affecting the dictionary itself; however, you can create the same list with list(dct), which works in both Python 2 and 3.
You indeed don't want any of these for iteration or membership testing; always use for key in dct and key in dct for those, respectively.
Source: PEP 234, PEP 3106
Python 2's relatively useless dict.keys method exists for historical reasons. Originally, dicts weren't iterable. In fact, there was no such thing as an iterator; iterating over sequences worked by calling __getitem__, the element access method, with increasing integer indices until an IndexError was raised. To iterate over the keys of a dict, you had to call the keys method to get an explicit list of keys and iterate over that.
When iterators went in, dicts became iterable, because it was more convenient, faster, and all around better to say
for key in d:
than
for key in d.keys()
This had the side-effect of making d.keys() utterly superfluous; list(d) and iter(d) now did everything d.keys() did in a cleaner, more general way. They couldn't get rid of keys, though, since so much code already called it.
(At this time, dicts also got a __contains__ method, so you could say key in d instead of d.has_key(key). This was shorter and nicely symmetrical with for key in d; the symmetry is also why iterating over a dict gives the keys instead of (key, value) pairs.)
In Python 3, taking inspiration from the Java Collections Framework, the keys, values, and items methods of dicts were changed. Instead of returning lists, they would return views of the original dict. The key and item views would support set-like operations, and all views would be wrappers around the underlying dict, reflecting any changes to the dict. This made keys useful again.
Assuming you're not using Python 3, list(dct) is equivalent to dct.keys(). Which one you use is a matter of personal preference. I personally think dct.keys() is slightly clearer, but to each their own.
In any case, there isn't a scenario where you "need" to use dct.keys() per se.
In Python 3, dct.keys() returns a "dictionary view object", so if you need to get a hold of an unmaterialized view to the keys (which could be useful for huge dictionaries) outside of a for loop context, you'd need to use dct.keys().
key in dict
is much faster than checking
key in dict.keys()