Well they are the same in this particular example. As you can see:
>>> states.items()
dict_items([('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')])
>>> type(_)
<class 'dict_items'>
>>>
The items function returns a dict_items object.
And it has a __iter__ attribute:
>>> dir(states.items())
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'isdisjoint']
>>>
Which means it supports iteration.
But if you try anything with it:
>>> states.items()[0]
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
states.items()[0]
TypeError: 'dict_items' object is not subscriptable
>>>
It would give a TypeError.
The dict_items class is something like:
class dict_items:
...
def __iter__(self):
...
It supports iteration but nothing else.
Whereas if you convert it to a list:
>>> list(states.items())
[('Oregon', 'OR'), ('Florida', 'FL'), ('California', 'CA'), ('New York', 'NY'), ('Michigan', 'MI')]
>>>
It would give a regular list of tuples, that is obviously iterable as well, but it is completely not needed in this situation.
As @juanpa.arrivillaga mentioned, using list(states.items()) needlessly creates a list of tuples and iterates over that instead of iterating over the items-view directly.
In some other situations, using list is required. If you want to convert a dictionary to a list of tuples, list(states.items()) would be the way to go.