2

I come from a solid Java (and Matlab) background, and have been trying to teach myself Python (3.4) recently. In the Java API docs (http://docs.oracle.com/javase/7/docs/api/), the documentation for a particular class always shows a nice overview of the ancestors of that class (see e.g. this screenshot).

Now I'm wondering if there is any way of viewing a similar ancestor hierarchy for Python classes. I am working from the assumption that, since Python is an object-oriented language, all non-primitive types will be objects (please correct me if I'm wrong). Understanding the ancestry for different types should probably greatly aid my understanding of iterables, sequences, views, and lists.

I've tried several things, as suggested in answers to similar questions (such as here); but inspect.mro(cls) does not always seem to work; for instance, the following gives an error:

inspect.getmro(dict_keys)

even though dict_keys is a type:

In[30]: type({}.keys()) Out[30]: dict_keys

I was also highly surprised to learn that list does not inherit from iterable:

In[34]: inspect.getmro(list) Out[34]: (list, object)

So, although my question is mainly about how to view (and, ideally, browse) the hierarchy of the standard Python library, any other comments on how to understand the default types' hierarchy, mainly how lists/sequences/views/iterables relate formally, would also be very welcome. The (otherwise excellent) Python tutorial does not really cover this stuff, it seems.

Community
  • 1
  • 1
EelkeSpaak
  • 2,757
  • 2
  • 17
  • 37

1 Answers1

2

Just because something is a type doesn't mean you have a reference to that type in the global namespace. This is the case with dict_keys. e.g.

>>> inspect.getmro(type({}.viewkeys()))  # using python2.x :-(
(<type 'dict_keys'>, <type 'object'>)

So it does have an MRO, and it is inspectable -- You just didn't have a handle on the dict_keys type before now.

Note that the MRO can be a bit deceiving:

>>> import collections
>>> issubclass(list, collections.Iterable)
True

so we see that list at least thinks that it is a subclass of collections.Iterable even though you won't find it in the MRO. This is because collections.Iterable actually registers itself using the abc module.

I think that this is one of the basic differences between python and java. In python, you typically care more about the interface the object provides rather than the actual type and inheritance tree. At some level this statement may seem a bit pedantic -- After all, you need to know the inheritance tree to know the interface an object provides. But the fact that we work in interfaces is exactly why tuple, list and generator objects can be iterated over despite not having a real common base class (collections.Iterable doesn't count as it is a virtual base class) above object (which can't be iterated over).

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Ah thanks, that at least answers part of my confusion. Thinking about it, if of course makes sense that dict_keys did not exist in the global namespace if I didn't explicitly import it. It still leaves open the question of whether there is a convenient way of browsing the class hierarchy, though. But I'm starting to suspect this hierarchy is a lot more complicated for Python than for Java, what with "virtual subclasses" etc. :) In Java every class (except Object) has exactly one parent, and additionally can implement any number of interfaces. This may be misleading me. – EelkeSpaak Nov 05 '14 at 16:40
  • @EelkeSpaak: Indeed, one of Java's fundamental design choices was to only support single inheritance. Python allows multiple inheritance. mgilson's answer mentions "interfaces" in a plain-English way, but of course Java has an actual language construct called `interface`, which it could be argued complicates class relationships in ways reminiscent of multiple inheritance. Ultimately, while I do think some knowledge of Java can help in learning Python, you have to be careful not to take analogies too far. – John Y Nov 05 '14 at 17:38
  • @JohnY -- Thanks. Unfortunately I don't know a whole lot of Java so I can't take things too far. I mean "interface" in the go-lang sense of the word. Of course there it's a formal concept too whereas what I'm talking about is much less formal. – mgilson Nov 05 '14 at 19:32
  • @mgilson: The "taking things too far" part of my comment wasn't directed at you. It was directed at folks who are trying to "bootstrap" their Python knowledge by applying what they know from Java. Some Pythonistas recommend unlearning everything Java when learning Python; personally I don't think that's necessary, but then I do have to stress that the similarities can only take you so far. – John Y Nov 05 '14 at 20:10
  • @JohnY -- Cool. As somebody who hopes to learn a little java in the near future, it's good to know that I might not have to unlearn _all_ my python ;-). Thanks for the comments. – mgilson Nov 05 '14 at 20:57