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 __mro__
"attribute" is a data descriptor , similar toproperty
. 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.