28

How to access "myvar" from "child" in this code example:

class Parent():
    def __init__(self):
        self.myvar = 1

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)

        # this won't work
        Parent.myvar

child = Child()
  • 1
    if your attribute starts with a 'dunder' (e.g. `self.__myvar`) it won't work as python considers it private – ihadanny Feb 28 '21 at 18:24
  • Based on the way your code is written, I could interpret this question in two ways. Either, 1) You're asking "From a subclass, how do I access names that are defined in its superclass?" Or 2) you're confused about the difference between a class variable and an instance variable – Alex Oakley Jul 21 '23 at 05:46

5 Answers5

39

Parent is a class - blue print not an instance of it, in OOPS to access attributes of an object it requires instance of the same, Here self/child is instance while Parent/Child are classes...

see the answer below, may clarify your doubts.

class Parent():
    def __init__(self):
        self.myvar = 1

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)

        # here you can access myvar like below.
        print self.myvar

child = Child()
print child.myvar
Japan Shah
  • 414
  • 3
  • 3
  • 2
    I could have sworn I tried the normal "self" instance reference. Oh well. Waiting to accept answer... –  Jun 06 '12 at 06:23
  • Note: in this case, you don't need to have an init method in the subclass for this solution to work. – Ahmed Alhallag Sep 01 '20 at 04:43
  • 2
    For future readers, the `super()` method is preferred in the child class `__init__` instead of the parent class name. See [this question](https://stackoverflow.com/q/222877/8213085) – Bilbottom Apr 17 '21 at 13:37
10

Parent does not have an attribute called myvar. Only instances of parent have that attribute. From within a method of Child, you can access that attribute with self.myvar.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
7

Alternative to using inheritance

The current answers are coming from an inheritance perspective, but this isn't always what you want -- sometimes you might want the child to be an entirely different type of object to the parent, but that still has access to the parent attributes.

For a business analogue, think of Excel Workbooks which have Worksheet children, which themselves have Range children, and so on.

Only Child

An alternative approach (and not the only one) is to pass the parent as an argument to the child to create a property that corresponds to the parent:

class Parent(object):
    def __init__(self, parent_value):
        self.parent_value = parent_value
        self.child = Child(self)


class Child(object):
    def __init__(self, _parent):
        self.parent = _parent
        self.child_value = 0


new_parent = Parent(1)
print(new_parent.parent_value)        # prints 1

new_child = new_parent.child
print(new_child.child_value)          # prints 0
print(new_child.parent.parent_value)  # prints 1

new_parent.parent_value = 100
print(new_child.parent.parent_value)  # prints 100

Note that this instantiates the child at the same that that new_parent is instantiated. To access the parent's attributes, just go through the parent property.

Multiple Children

You could extend this so that you can create multiple instances of the Child class through the new_parent object. The code below is one simple way of doing this which replaces the child property with a children property and an add_child method.

class Parent(object):
    def __init__(self, parent_value):
        self.parent_value = parent_value
        self.children = []

    def add_child(self, child_value):
        new_child = Child(child_value, _parent=self)
        self.children.append(new_child)
        return new_child  # allows add_child to assign a variable


class Child(object):
    def __init__(self, child_value, _parent):
        self.parent = _parent
        self.child_value = child_value


new_parent = Parent(1)

# add 3 Child instances with child_values 2, 4, 8
[new_parent.add_child(v) for v in [2, 4, 8]]

# add another child that utilises the return statement
extra_child = new_parent.add_child(16)

for child in new_parent.children:
    print(child.child_value)          # prints 2, 4, 8, 16
    print(child.parent.parent_value)  # prints 1

new_parent.parent_value = 32
for child in new_parent.children:
    print(child.parent.parent_value)  # prints 32

# prove that extra_child is new_parent.children[3]
extra_child.child_value = 64
print(new_parent.children[3].child_value)  # prints 64
Bilbottom
  • 725
  • 8
  • 12
  • 3
    Whilst your answer is good quality, I don't think your answer answers the question as is. The question asks about inheritance not about composition or container classes. And I honestly don't think the OP needs to employ composition here. – Peilonrayz Apr 18 '21 at 14:09
0

One reason your code won't work, and has nothing todo with Parent/Child relationship, is that myvar is an instance variable but you're trying to access it like a class variable.

The following treats the variable as class variable and will work as expected:

class Parent():
    myvar = 1
    def __init__(self) -> None:
        # Move the definition of myvar outside of the __init__ method, 
        # and remove the self. prefix
        ...

class Child(Parent):
    def __init__(self) -> None:
        print(Parent.myvar) # 1

child =  Child()
        

In your original code;

class Parent():
    def __init__(self):
        self.myvar = 1 # this is an instance variable

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)

        # this won't work
        Parent.myvar #  this treats `myvar` as a class variable
Alex Oakley
  • 129
  • 10
-1

You need to initiate the parent class first via so-called proxy object using command "super".

So the code will be like this:

class Parent():
  def __init__(self):
      self.myvar = 1

class Child(Parent):
  def __init__(self):
      super.__init__()


child = Child()
print child.myvar
Shtefan
  • 742
  • 12
  • 14
  • I'm not sure what's wrong with this answer. Could someone enlighten me? – Alex Oakley Jul 21 '23 at 05:31
  • This answer uses python 2.x, which is deprecated. Also, it doesn't really answer the question, because OP asked to access "myvar" inside the "child" class. – Eddudos Kim Jul 21 '23 at 06:28
  • what an expert :) Kim you are wrong. Answered exactly as it was asked. And the solution works on any version of Python. Many people strugeling to understand the concept of parent class. And looks like you one of them. – Shtefan Jul 22 '23 at 06:58