Reputation: 4637
Is it a general rule that native Python classes, e.g. os.stat_result
, have no __dict__
attribute (as for instance suggested in how to avoid class having a __dict__)?
What are the technical reasons why built-in classes (e.g. os.stat_result
) lack this feature?
Upvotes: 1
Views: 595
Reputation: 110311
I don't know if there is a "correct" answer for this - the reasoning is that for most of these objects one can happily live without attaching extra-attributes to their instances - and the cost of having a __dict__
is simply not worth it.
Can you try imagining if Python's int
s had __dict__
s? For every number, beside the 80-something bytes it takes, another 200-ish byte object would be built, so that one could have attributes to pegged to their "42"?
Also, for imutable classes, like tuples, strings, and such, the same instance can be reused in different contexts - a __dict__
in one instance could make a seemingly non-connected instance of the same object to suddenly spawn attributes.
Also, the specific class you mention os.stat_result
is a named-tuple - it is meant to be immutable and compact.
So, besides the size and resource cost of creating __dict__
for most objects, there is also the coding issue: these are usually natively coded (i.e. written in C) - and th e __dict__
attribute would have to be explicitly created - so unlike classes coded in Python - one have to go out of his way to allow __dict__
in these classes, while for Python code, the detour is on avoiding __dict__
.
And finally, when the community developing the language concludes that there would be any clear advantage in an object having a __dict__
, it might be included. That happened with the Function object type itself a while ago - and functions now can have attributes attached to them by decorators, and this can be put to good use.
While if you need code attaching extra-attributes to a single class, you can do it the old-fashion way, and just inherit that class and convert your object to it. (I jut found out that os.stat_result
is not a named_tuple, and can't be used as a base class - sorry for that - so, wrapping it in a simple class might be the simplest thing to do:
class MyStatResult:
def __init__(self, stat_result):
self.stat = stat_result
def __repr__(self):
return "Wrapper for" + repr(self.stat)
Now, if your goal is to extract the fields titles/values as a dict, and not adding extra attributes to it - the introspectable part of these objects is given by dir
- in the case of os.stat_result
the fieds that matter have a nice prefix:
stat = os.stat(path)
stat_dict = lambda path: {name: getattr(stat, field) for field in dir(stat) if field.startswith("st_")}
In Python 3.8, thanks to PEP 572, one will be able to write that as a nice oneliner:
stat_dict = lambda path: {name: getattr(stat, field) for field in dir(stat:=os.stat(path)) if field.startswith("st_")}
Upvotes: 4