Reputation: 95
I understand that you can view things within Python as attributes as per this article. But I am curious as to why in an instance of a class, parent_instance
, we do not have the same attributes stored within the ParentClass
. This question said that, "The '__dict__'
and '__weakref__'
entries in a class's __dict__
(when present) are descriptors used for retrieving an instance's dict pointer and weakref pointer"
I know that with a dir(parent_instace)
call, I can still obtain a '__weakref__'
, which will be None, and the method_1
and method_2
. But why aren't these within __dict__
in a similar format only set to None?
What is setting or defining what is in __dict__
? Why can I not access method attributes within an instance using __dict__
. I understand it's not within the scope, but why is it not in the scope? Shouldn't the method attributes be within the instance since it can access them?
Reference Code:
class ParentClass:
def __init__(self):
self.int_1: int = 0
self.str_1: str = ''
def method_1(self):
pass
def method_2(self):
pass
parent_instance = ParentClass()
print("Parent Class Attributes:")
for atr in ParentClass.__dict__:
print(atr)
print("\nParent Instance Attributes:")
for atr in parent_instance.__dict__:
print(atr)
Upvotes: 1
Views: 226
Reputation: 226256
You asked a lot of questions, but I think the common theme is "why doen't the instance dictionary store everything that is accessible from an instance?"
The answer is that instances store information unique to each instance while classes store information (methods and class variables) that are shared by all instances.
This is central to the notion of what it means to be class (what all instances have in common), and it is memory efficient (one class and many instances).
Users don't normally access the class __dict__
or instance __dict__
directly. They use dir()
to see all the levels collapsed to together and use either the dot operator or getattr()
to do a look up in the chain of dictionaries (instance first and the MRO of class dictionaries). From the user's point of view, almost everything is in the object.
There are some implementation nuances such as __mro__
being only accessible from the class and not from the instance. Also, the garbage collection, refcount, and weak reference support aren't shown in the instance dictionary even though they are part of the object.
A secondary question is "why don't classes list all attributes including instance attributes?"
There are two equivalent answers:
a) Since instance dictionaries are dynamically updatable and store both the key and value, there is no need to store this information at the class level.
b) Since instance attributes can be added after instantiation, the class cannot know in advance which attributes are going to be stored in instances.
This is true most of the time in Python (and other interpreted OOP languages). However, classes defined with __slots__
are an exception to this rule because they don't use instance dictionaries. Dataclasses may seem like an exception because they store code generation metadata at the class level, but after the code is generated they are just regular classes and the same principles apply.
Upvotes: 4