Why aren't dict.items() .keys() .values() properties?


{v: k for k, v in some_dictionary.items}

for sharedkey in dct1.keys & dct2.keys:  # intersection of two dictionaries
    print(dct1[sharedkey], dct2[sharedkey])

Probably for historical reasons.

Originally, in Python 1.x dict.keys() etc had to be methods because
there were no properties available.

In Python 2, after properties were introduced during the class/type
unification, backwards compatibility meant that .keys() etc had to stay
as methods.

In addition, there is a very strong tradition that properties should
only be used for values that are fast to compute. Anything that could
potentially be expensive (like walking a huge dict collecting keys and
values) should be a method call, to signal to the caller that it isn’t
just a quick attribute but could potentally take a while.

In Python 3, the meaning of .keys() etc changed again, to return a view
object which, I assume, could have been fast and cheap and so might have
been turned into a property.

But either nobody thought of it at the time, or thought that it wasn’t
worth breaking backwards compatibility.


With all of the other breaking changes in Python 2 → Python 3, I’m guessing that changing them from methods to attributes simply wasn’t worth the additional break in backwards compatibility.

Plus, there would be a significant relearning cost if Python developers had to remember to use dict.items instead of dict.items() (or dict.iteritems(), which replaced dict.items() in Python 3). Imagine the amount of code, documentation, and text books that would have to be rewritten if .items(), .values(), or .keys() no longer worked.

I’m of the opinion that there has to be a very clear benefit in one or multiple of: performance, efficiency, security, or readability for the relearning cost to be worthwhile. To me, there seems to be not enough of a substantial benefit from changing to dict.items() to dict.items (or the others), even if it might make slightly more sense as a property.

1 Like

I noticed that in asyncio, Van Rossum does not use properties at all, but “good old” getter and setter. Maybe it’s also a question of performance?

PS: even so, I usually write properties. They are more elegant and permit you to leave the attribute public for a fast and dirty implementation. If you need to encapsulate it later, with properties you can do it without changing the API.

Dictionaries change, which means what those methods return change over time. You don’t necessarily want to use attributes for data which is potentially in flux due to dict mutations (or expensive to calculate).

I think that @aoeu means that mydict.values and the others should always return a new _PyDictViewObject, but simply without the parentheses, as @property allows.

1 Like