Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: print base class variables

I'm using a library to share data between C++, VHDL, and SystemVerilog. It uses codegenerators to build datastructures that contain the appropriate field. Think of a c type data structure. I want to generate python code that contains the datastructure and read/write functions to set and write the contents of the datastructure from a / to a file.

To do this i am trying to write a program that prints all the variables in the baseclass with updates from the subclass, but without the subclass variables.

The idea being that class A is the actual VHDL/SystemVerilog/C++ record/structure and class B contains logic to do processing and generate the values in class A.

For example:

class A(object):
    def __init__(self):
        self.asd = "Test string"
        self.foo = 123

    def write(self):
        print self.__dict__

class B(A):
    def __init__(self):
        A.__init__(self)
        self.bar = 456
        self.foo += 1

    def write(self):
        super(B, self).write()

Calling B.write() should yield the following: (Note the incremented value of foo)

"asd: Test String, foo: 124"

but instead it yields

"asd: Test String, bar: 456, foo: 124".

Is there a way to only get the base class variables? I could compare the base dictionary with the subclass dictionary and only print the values that appear in both but this does not feel like a clean way.

like image 932
Maurice Avatar asked Nov 11 '15 10:11

Maurice


2 Answers

You said: "I could compare the base dictionary with the subclass dictionary and only print the values that appear in both but this does not feel like a clean way". What you're trying to do isn't a natural thing to do in Python, so no matter what you do, it's not going to be clean. But in fact, what you suggest is impossible, since you can't get the base dictionary when you make the .write call in a B instance. The closest you can do is to take a copy of it (or, as Daniel Roseman suggests, its keys) immediately after the __init__ call in B so you can refer to that copy later when you need it.

Here's some code that does that:

class A(object):
    def __init__(self):
        self.asd = "Test string"
        self.foo = 123

    def write(self, d=None):
        print self.__dict__

class B(A):
    def __init__(self):
        A.__init__(self)
        self.parentkeys = self.__dict__.keys()
        self.bar = 456
        self.foo += 1

    def write(self):
        bdict = self.__dict__
        print dict((k, bdict[k]) for k in self.parentkeys)


a = A()
b = B()
a.write()
b.write() 

output

{'foo': 123, 'asd': 'Test string'}
{'foo': 124, 'asd': 'Test string'}

Here's a minor variation:

class A(object):
    def __init__(self):
        self.asd = "Test string"
        self.foo = 123

    def write(self, d=None):
        if d is None:
            d = self.__dict__
        print d

class B(A):
    def __init__(self):
        super(B, self).__init__()
        self.parentkeys = self.__dict__.keys()
        self.bar = 456
        self.foo += 1

    def write(self):
        bdict = self.__dict__
        d = dict((k, bdict[k]) for k in self.parentkeys)
        super(B, self).write(d)

However, I get the feeling that there may be a more Pythonic way to do what you really want to do...

like image 34
PM 2Ring Avatar answered Sep 19 '22 19:09

PM 2Ring


There is no distinction between base class and subclass variables. By definition, inheritance is an is-a relationship; everything defined in the base class is as if it was defined in the subclass.

Similarly, anything you define on the instance at any other point in your code will also appear in the dict; Python does not restrict you from adding new instance variables elsewhere in the class or even from outside.

The only way to do what you want is to record the keys when you enter A.__init__.

like image 69
Daniel Roseman Avatar answered Sep 21 '22 19:09

Daniel Roseman