watashiSHUN
watashiSHUN

Reputation: 10504

where does python store inheritance information in a class?

python version 3.5.2
I tried to get parent class from a child class:

class A:
    pass
class B(A):
    pass

after a little research, I got a solution from python doc: use __base__. (a special class attribute) But I couldn't find this "__base__" in B.__dict__ or dir(B), which are my normal ways of getting attributes.

This is definitely class related information, if it's not in B.__dict__ where is it? (although I realized that "__base__" is returned by type(B).__dict__)
And why isn't dir() returning it? based on this stackoverflow question I read, dir() has some logics behind and it is supposed to return "a complete picture of all available attributes."

I initally thought this is hiding on purpose...but you can still easily manipulate a child's parent:

class C:
    pass
B.__bases__ = (C,) # voila, B got a new Dad

Upvotes: 1

Views: 86

Answers (1)

poke
poke

Reputation: 387677

See the note on dir() (emphasis mine):

Note: Because dir() is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.

B is a class, its metaclass is type. So if you really want the full picture, you should also look as the metaclass’ dir():

>>> B.__class__ is type
True
>>> dir(type)
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__',
 '__delattr__', '__dict__', '__dictoffset__', '__dir__', '__doc__', '__eq__', '__flags__',
 '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
 '__init_subclass__', '__instancecheck__', '__itemsize__', '__le__', '__lt__',
 '__module__', '__mro__', '__name__', '__ne__', '__new__', '__prepare__', '__qualname__',
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
 '__subclasscheck__', '__subclasses__', '__subclasshook__', '__text_signature__',
 '__weakrefoffset__', 'mro']

And there you have __base__ and __bases__, and also those other things that appeared in the list you linked, like mro and __subclasses__.

Upvotes: 1

Related Questions