[Python] Class Properties that have their own Properties

I’m doing an exercise in Class design and I’m having some problems wrapping my head around a particular problem.

Here is some pseudo code that demonstrates the functionality I would like:


MyClass = Mesh('pCube1') # this class automatically adds a user-defined Boolean attribute, export, and creates a class property to manage it.
MyClass.export = True
MyClass.export
# Result: True
MyClass.export.lock = True # this fails
MyClass.export.lock
# Result: True

The snag I am hitting is when I try to Lock the Property.

# AttributeError: 'bool' object has no attribute 'lock'

It is my understanding that this is happening:

MyClass.export.lock = True > True.lock = True

How do I get the Property Class back instead of its value?

i’d need to see the entire class def. The properties would just be get/set functions no? What object would you expect back?

You’ve already told python that the name ‘Export’ in the Mesh class contains the boolean value ‘True’. Bool objects’s don’t have a ‘lock’ property.

To write it the way you want, you need to do one of the following things:

  1. The value you put into export is not a pure boolean, but a class that ‘looks’ like a boolean. That would mean you’d have write something like

Myclass.Export = LockableBool(True)
Myclass.Export.Lock = True

  1. (the easy way) Dont’ use nested properties, use methods:

Class MyClass (object):
     def __init__(self):
          self._export = False;
          self._lock_export = False;

     def set_export(self, val):
         if self._lock_export: raise RuntimeError ("Export value is locked")
         self._export = val

     def get_export(self):
         return self._export


     def lock_export(self):
         self._lock_export = True

     def unlock_export(self):
        self._lock_export = False

  1. Same as (2) except that you can make the ‘export’ into a property:

Class MyClass (object):
     def __init__(self):
          self._export = False;
          self._lock_export = False;

     @property
     def export(self):
         return self._export

     @export.setter
     def set_export(self, val):
         if self._lock_export: raise RuntimeError ("Export value is locked")
         self._export = val

     def lock_export(self):
         self._lock_export = True

     def unlock_export(self):
        self._lock_export = False

  1. If you’re really desperate for nested properties as in the original post, you can combine (1) and (3) so that the hidden inner object is always a LockableBool object:

     # in the init, make sure the hidden _export field is a LockableBool().  I'm pretending 'val' is the actual true-false value of that class...

     @export.setter
     def set_export(self, val):
         if self._lock_export.lock: raise RuntimeError ("Export value is locked")
         self._export.value = val


… I should have mentioned that many people frown on the use of deeply nested properties in the first place. The theory is that they involve too much extra knowledge: the use has to know not only about the abilities of MyClass() but also those of LockableBool(), etc. However that’s one of those programmer flame war topics that will never end :slight_smile:

thanks for your input, i’ll mull it over!