1

I have a base class A, inherited by classes B and C, from which I was trying to set an instance variable. Such variable is used by methods from base class A as follows.

class A(object):
    def foo(self):
        print(self.value)

class B(A):
    value = "B"

class C(A):
    value = "C"

>>> b = B()
'B'
>>> c = C()
'C'

I understand function foo will only be evaluated during execution, which is fine as long as I do not invoke foo straight from an instance of A. Yet, I fail to grasp how value = "B" and value = "C" manage to become self.value = "B" and self.value = "C".

Sorry if this is naive question; I have been far from python for quite a while now, and really had not seen anything quite like it. I'm using Python version 2.7.12.

Rubens
  • 14,478
  • 11
  • 63
  • 92
  • 2
    They are not instance variables, they are class-level variables being accessed from an instance. – juanpa.arrivillaga Oct 26 '17 at 03:45
  • @juanpa.arrivillaga But should not this access happen through `value` instead of `self.value`? Why does `self.value` work? – Rubens Oct 26 '17 at 15:09
  • 1
    No. `value` is not defined in any scope. That would raise a `NameError`. You can use `MyClass.value` or `my_instance.value`, but just `value` will try to find a local variable or a global variable. When a attribute on an instance is accessed, first it checks the namespace of the instance, if it isn't found, it checks the namespace of the class, and then all the classes in the MRO until the name is resolved or an `AttributeError` is raised. That's inheritance in a nutshell. See [this question](https://stackoverflow.com/questions/10313471/python-access-class-variables-via-instance) – juanpa.arrivillaga Oct 26 '17 at 16:17

1 Answers1

1

You cannot add an instance variable to a base class in Python, because instance variables can only be added to instances, not classes.

In your example, "value" is a class variable. In Python, when there is no instance variable with a given name, it falls back to the class variable with that name. However, if you assigned a new value to b.value, that would create an instance variable on b. B.value would be unaffected, as would any new instances of B.

I didn't find an authoritative reference for the behavior, but here's an article about it. https://www.toptal.com/python/python-class-attributes-an-overly-thorough-guide

Aaron Bentley
  • 1,332
  • 8
  • 14
  • Ah, I really did not know that *when there is no instance variable with a given name, it falls back to the class variable with that name*. Would you suggest some reference, so I can better understand this default behavior definition? Thank you in advance. – Rubens Oct 26 '17 at 15:12
  • 1
    I didn't find an authoritative reference before my original post, so I didn't include one. I've updated my answer to include an article. – Aaron Bentley Oct 26 '17 at 17:47
  • 1
    @Rubens all the details are in the [data model](https://docs.python.org/3/reference/datamodel.html#), so for example this snippet: "Custom class types are typically created by class definitions (see section Class definitions). A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary, e.g., `C.x` is translated to `C.__dict__["x"]` (although there are a number of hooks which allow for other means of locating attributes). **When the attribute name is not found there, the attribute search continues in the base classes.**" – juanpa.arrivillaga Oct 26 '17 at 18:05