Let's say there is some class:
class Test():
pass
(1)Somewhere on SO and in documentation i read next:
mro()
called at class instantiation, and its result is stored in__mro__
.
Okay, that is still clear to me, cause in __mro__
something is really stored:
Test.__mro__
Out[48]: (__main__.Test, object)
Again, somewhere i read this:
To look up an attribute name Python searches:
a)Search the__dict__
of all metaclasses on the__mro__
found at C’s__class__
.
b)If a data descriptor was found in step a, call its__get__()
and exit.
c)Else, call a descriptor or return a value in the__dict__
of a class on C’s own__mro__
.
d)Call a non-data descriptor found in step a.
e)Else, return Metaclass-tree values
I can find out that there is no __mro__
in Test.__dict__
:
'__mro__' in Test.__dict__
Out[49]: False
So accordingly to e
clause from previous quote i guess that
__mro__
should be taken from "Metaclass-tree values" and hence from type.__dict__
Really, there is __mro__
in type.__dict__
:
["mro:<method 'mro' of 'type' objects>",
"__mro__:<member '__mro__' of 'type' objects>"]
So what was mentioned above in (1) about mro()
result stored in __mro__
attribute from documentation doesn't really works this way?
How does <member '__mro__' of 'type' objects>
results to (__main__.Test, object)
?
Maybe you could show some source code to understand what really happens when i call Test.__mro__
..
The Method Resolution Order (MRO) is the set of rules that construct the linearization. In the Python literature, the idiom "the MRO of C" is also used as a synonymous for the linearization of the class C.
Attributes of a class can also be accessed using the following built-in methods and functions : getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute.
All objects in Python have an attribute __dict__, which is a dictionary object containing all attributes defined for that object itself. The mapping of attributes with its values is done to generate a dictionary.
Method Resolution Order(MRO) it denotes the way a programming language resolves a method or attribute. Python supports classes inheriting from other classes. The class being inherited is called the Parent or Superclass, while the class that inherits is called the Child or Subclass.
The __mro__
"attribute" is a data descriptor, similar to property
. Instead of fetching the __mro__
attribute value from __dict__
, the descriptor fetches the value from another place or computes it. In specific, a <member '...' of '..' objects>
indicates a descriptor that fetches the value from an VM-internal location – this is the same mechanism used by __slots__
.
>>> class Bar:
... __slots__ = "foo",
...
>>> Bar.foo
<member 'foo' of 'Bar' objects>
>>> 'foo' in Bar.__dict__
True
Descriptors are inherited without duplication, and thus do not appear explicitly on subclasses.
>>> class Foo(Bar):
... __slots__ = ()
...
>>> Foo.foo
<member 'foo' of 'Bar' objects>
>>> 'foo' in Foo.__dict__
False
The precise working of such a member
data descriptor is implementation defined. However, logically they work the same as a property
using an internal storage:
class FooBar:
def __init__(self, foo, bar):
# attributes stored internally
# the "_data" of a member is not visible
self._data = [foo, bar]
@property
def foo(self):
return self._data[0]
@foo.setter
def foo(self, value):
self._data[0] = value
@property
def bar(self):
return self._data[1]
@bar.setter
def bar(self, value):
self._data[1] = value
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With