3

I've created a class object called 'Node'. I then created two subclasses 'Beetle' and 'Dakota'. You'll notice there is an attr called 'superclass' which is part of the baseclass. I want this attribute to be set for each subclass and once it's set it should never be changed. It's a read-only attribute. I was wondering how to set this attribute up correctly in order to be a read only attribute?

class Node(object):
    def __init__(self, name, superclass, attributes, children):
        self.name = name
        self.superclass = superclass
        self.attributes = attributes if attributes is not None else {}
        self.children = children if children is not None else []


    class Beetle(Node):
        def __init__(self, name="", superclass="Cars", attributes=None, children=None, enabled=True):
            super(Beetle, self).__init__(name=name, superclass=superclass, attributes=attributes, children=children)
            self.enabled = enabled


    class Dakota(Node):
        def __init__(self, name="", superclass="Trucks", attributes=None, children=None, enabled=True):
            super(Dakota, self).__init__(name=name, superclass=superclass, attributes=attributes, children=children)
            self.enabled = enabled
Ayush
  • 3,695
  • 1
  • 32
  • 42
JokerMartini
  • 5,674
  • 9
  • 83
  • 193
  • The answers to [this question](http://stackoverflow.com/questions/14594120/python-read-only-property) seem relevant. – Matt Hall Nov 23 '15 at 13:57

2 Answers2

2

To have a 'read-only' property in a class you can make use of the @property decoration.

An example:

class Dakota(object):
def __init__(self, superclass):
    self.__superclass = superclass

    @property
    def superclass(self):
        return self.__superclass

Usage:

>>> a = Dakota('lol')
>>> a.superclass
'lol'
>>> a.superclass = 'hah'
AttributeError...    

AttributeError: can't set attribute

You can refer to this other answer thread

Community
  • 1
  • 1
mattgathu
  • 1,129
  • 1
  • 19
  • 28
  • 2 ways to set the attribute: 1 (set the attribute) `a._Dakota__superclass = None`; 2 (add a setter to `Dakota.superclass.fset`) `Dakota.superclass.__init__( Dakota.superclass.fget, lambda self,value: setattr(self,'_%s__superclass'%(self.__class__.__name__),value) )` (it's funny how `slice()` has more security than `property()` haha) – Tcll Jul 08 '23 at 22:32
1

Rename you variable to add __ to the begining

self.__superclass = superclass

you can't access self.__superclass with something like Dakota().__superclass

if you want to get value of __superclass add a function in Node class to return it.

def getsuperclass(self):
    return self.__superclass
...

Dakota().getsuperclass()
Kenly
  • 24,317
  • 7
  • 44
  • 60