The way how attributes are collected from super classes is different comparing to how attributes and methods are searched by getattr (based on MRO for new-style classes).
Example:
@attr.s
class A(object):
x = attr.ib(10)
def xx(self):
return 10
@attr.s
class B(A):
y = attr.ib(20)
@attr.s
class C(A):
x = attr.ib(50)
def xx(self):
return 50
class D(B, C):
pass
d = D()
print(d.x) # prints 10
print(d.xx()) # prints 50
I think it would be great to the use the same approach for collecting attributes as used for searching methods and attributes.
The difference is caused by the fact that the function _transform_attrs in attrs/_make.py considers all attributes (own+inherited stored in __attrs_attrs__) and not only own attributes of super classes:
|
for super_cls in cls.__mro__[1:-1]: |
|
sub_attrs = getattr(super_cls, "__attrs_attrs__", None) |
The way how attributes are collected from super classes is different comparing to how attributes and methods are searched by
getattr(based on MRO for new-style classes).Example:
I think it would be great to the use the same approach for collecting attributes as used for searching methods and attributes.
The difference is caused by the fact that the function
_transform_attrsinattrs/_make.pyconsiders all attributes (own+inherited stored in__attrs_attrs__) and not only own attributes of super classes:attrs/src/attr/_make.py
Lines 367 to 368 in 6a07b03