Based on what I was seeing here, I did some experiments to try to understand
better what is going on:
class BaseClass:
def __init__(self):
self.a = 1
def base_method(self):
return self.a
def another_base_method(self):
return self.a + 1
class SubClass(BaseClass):
def __init__(self):
super().__init__()
self.b = 2
c = SubClass()
print(c.__dict__)
print(c.__class__.__dict__)
print(c.__class__.__subclasses__())
print(c.__class__.mro())
print(c.__class__.mro()[1].__dict__)
print(getattr(c, "base_method"))
print(c.b)
print(c.a)
With some notes:
print(c.__dict__)
{'a': 1, 'b': 2}
So the instance directly has a. I am guessing that the object's own dictionary
is directly getting these are both __init__'s are run.
print(c.__class__.__dict__)
{'__module__': '__main__', '__init__': <function SubClass.__init__ at
0x000001BEEF46E488>, '__doc__': None}
I am guessing this is what is found and stuffed into the class' namespace when
the class is built; that's specifically the BUILD_CLASS opcode doing its thing.
print(c.__class__.__subclasses__())
[]
What?! Why isn't this [<class '__main__.BaseClass'>]?
print(c.__class__.mro())
[<class '__main__.SubClass'>, <class '__main__.BaseClass'>, <class 'object'>]
This is more like what I expected to find with subclasses. Okay, no, method
resolution order is showing the entire order.
print(c.__class__.mro()[1].__dict__)
{'__module__': '__main__', '__init__': <function BaseClass.__init__ at
0x000001BEEF46E2F0>, 'base_method': <function BaseClass.base_method at
0x000001BEEF46E378>, 'another_base_method': <function
BaseClass.another_base_method at 0x000001BEEF46E400>, '__dict__': <attribute
'__dict__' of 'BaseClass' objects>, '__weakref__': <attribute '__weakref__' of
'BaseClass' objects>, '__doc__': None}
No instance-level stuff. Looks like it's the base class namespace when the
BUILD_CLASS opcode saw it. Okay, looking good.
print(getattr(c, "base_method"))
<bound method BaseClass.base_method of <__main__.SubClass object at
0x000001BEEF2D9898>>
I'm guessing here it didn't find it in the object's __dict__ nor the class'
__dict__ so it went in mro and found it in BaseClass.
So I need a __dict__ for the class based on the code defined for it when the
class is defined. That's associated with the class. I need another dictionary
for each instance. That will get stuffed with whatever started getting dumped
into it in __init__ (and possibly elsewhere afterwards).
What __dict__ actually is can vary. The mappingproxy helps make sure that
strings are given as keys (among other things?).
--
https://mail.python.org/mailman/listinfo/python-list