Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get attribute from a super class in python

I have a base class, a bunch of subclasses, and for each of these subclasses, I have another set of sub-subclasses. For example:

class BaseClass(object):
    def __init__(self):
        with open(config.txt) as f
            self.config_array = f.readlines()

class FirstOrderSubClass(BaseClass):
    def __init__(self, name):
        self.name = name

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version):
        self.name = name
        self.version = version
        super(SecondOrderSubClass, self).__init__(self.name)
        # needed to access self.config_array
        print self.config_array

I need to get the __init__() method of the SecondOrderSubClass to make the following assignment: self.lines = self.config_array.

EDIT: added line print self.config_array. If I run the code I get:

TypeError: __getattr__() takes exactly 1 argument (2 given)
like image 403
rafforaffo Avatar asked May 28 '15 08:05

rafforaffo


People also ask

How do you access the super class variable in Python?

Super() Function in python By using the super() function, we can access the parent class members from the child class. The super() function is a built-in function, which is useful to call the superclass constructor, methods, and variables explicitly from the child class.

How do you access the attributes of a class in Python?

Accessing the attributes of a class getattr() − A python method used to access the attribute of a class. hasattr() − A python method used to verify the presence of an attribute in a class. setattr() − A python method used to set an additional attribute in a class.

How do you get attributes from parent class?

Accessing Parent Class Functions But have you ever wondered how to access the parent's class methods? This is really simple, you just have to call the constructor of parent class inside the constructor of child class and then the object of a child class can access the methods and attributes of the parent class.

What does super () __ Init__ do in Python?

The “__init__” is a reserved method in python classes. It is known as a constructor in Object-Oriented terminology. This method when called, allows the class to initialize the attributes of the class. The super() function allows us to avoid using the base class name explicitly.


2 Answers

You cannot access self.config_array until BaseClass.__init__() has run to set the attribute.

Either fix FirstOrderSubClass to also invoke the base class __init__ or call it directly.

Fixing the FirstOrderSubClass is probably the best way to do so:

class FirstOrderSubClass(BaseClass):
    def __init__(self, name):
        super(FirstOrderSubClass, self).__init__()
        self.name = name

However, your __init__ method signatures do not match so you cannot rely on cooperative behaviour here; as soon as you add a mix-in class in the hierarchy, things can and probably will break. See *Python's super() is considered super! by Raymond Hettinger, or it's followup PyCon presentation to explain why you want your signatures to match.

Calling the BaseClass.__init__ unbound method directly (passing in self explicitly) would also work:

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version):
        super(SecondOrderSubClass, self).__init__(name)
        self.version = version
        BaseClass.__init__(self)

Note that there is no point in assigning to self.name there if you are going to ask FirstOrderSubClass.__init__ to do the exact same thing.

The proper way to use super() is for all your methods to at least accept all the same arguments. Since object.__init__() never does, this means you need a sentinel class that does not use super(); BaseClass will do nicely here. You can use *args and **kw to capture any additional arguments and just ignore those to make cooperative subclassing work:

class BaseClass(object):
    def __init__(self, *args, **kw):
        with open(config.txt) as f
            self.config_array = f.readlines()

class FirstOrderSubClass(BaseClass):
    def __init__(self, name, *args, **kw):
        super(FirstOrderSubClass, self).__init__(*args, **kw)
        self.name = name

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version, *args, **kw):
        super(SecondOrderSubClass, self).__init__(name, *args, **kw)
        self.version = version
like image 156
Martijn Pieters Avatar answered Oct 05 '22 18:10

Martijn Pieters


You have to call the FirstOrderSubClass super method:

class BaseClass(object):
    def __init__(self):
        with open("config.example.txt",'w') as f:
            f.write("Hello world")
        with open("config.example.txt") as f:
            self.config_array = f.readlines()

class FirstOrderSubClass(BaseClass):
    def __init__(self, name):
        super(FirstOrderSubClass,self).__init__()
        self.name = name

class SecondOrderSubClass(FirstOrderSubClass):
    def __init__(self, name, version):
        self.name = name
        self.version = version
        super(SecondOrderSubClass, self).__init__(self.name)
        # needed to access self.config_array

grandchild = SecondOrderSubClass("peter",2.0)
print grandchild.config_array
##>>> 
##['Hello world']
like image 33
Sebastian Wozny Avatar answered Oct 05 '22 20:10

Sebastian Wozny