0

With a boring class, object instance attribute shadow class attributes:

class C(object):
    a="class_a"

    def __init__(self, a):
        self.a = a


c = C(a="obja")
print c.a  # obja

But if my class attributes are declared in a named_tuple base:

class C(collections.namedtuple("CBase", ['a', ])):
    a="class_a"

c = C(a="obja")
print c.a  # class_a !!??!

... so, declaring my instance attribute through the name tuple causes that attribute to be shadowed by the class attribute ... which not what you'd expect.

Why is this?

user48956
  • 14,850
  • 19
  • 93
  • 154

1 Answers1

3

namedtuple "attributes" are implemented as descriptors (specifically, propertys) on the class itself, not attributes in the traditional sense (all the actual data is stored in unnamed indices of the tuple). In this case, the namedtuple (roughly) defines:

@property
def a(self):
    return self[0]

Since the property is a class level attribute, when you define a on the subclass, it shadows equivalent definitions in the parent class.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • For those who care, the actual implementation (as of 3.6) wraps [an `operator.itemgetter`](https://docs.python.org/3/library/operator.html#operator.itemgetter) using `property`; the code I wrote is more recognizable to beginners though, so I omitted the specific implementation details. Either way, the actual behavior is identical. – ShadowRanger Apr 03 '18 at 02:23