0

I have a class who's fields are an instance of another class.

class Field:
    def get(self):
    def set(self, value):
    def delete(self):

class Document:
    def __init__(self):
        self.y = Field()
        self.z = True

What I'd like to be able to do is when an instance of the parent refers to its attributes, instead it calls the child's methods.

d = Document()
d.y = 'some value'  # Calls the `set` function of the Field
d.y == 'some value'  # Calls the `get` function of the Field
del d.y  # Calls the `delete` function of the Field

The other catch is that I only want this behavior when the field is of type Field.

I'm running into recursion problems try to use __getattr__ and the like, along the lines of:

def __getattr__(self, key):
    if isinstance(getattr(self, key), Field):
        return getattr(self, key).get()
    return getattr(self, key)

The recursion is fairly obvious why its happening... but how do I avoid it?

I've seen a few examples already on StackOverflow, but I can't seem to figure out how to get around it.

Community
  • 1
  • 1
heiskr
  • 395
  • 2
  • 11
  • 3
    Why not just use descriptors? This functionality is built in. – univerio Aug 23 '14 at 17:29
  • 1
    Wbat you're describing is pretty much exactly what descriptors are, except the method names are spelled `__get__`, `__set__` and `__delete__`, and the descriptor is set as an attribute of the class, not the instance. I'd suggest you look at some info about descriptors (e.g., [here](http://stackoverflow.com/questions/3798835/understanding-get-and-set-and-python-descriptors) and [here](http://nbviewer.ipython.org/urls/gist.github.com/ChrisBeaumont/5758381/raw/descriptor_writeup.ipynb)). – BrenBarn Aug 23 '14 at 17:34
  • Thanks! I'll try that, see how it goes. – heiskr Aug 23 '14 at 17:40
  • A side note idf you are nto using Python 3.x, always make your classes inherit from "object" – jsbueno Aug 23 '14 at 17:45

1 Answers1

1

What you are describing there is more or less exactly the innerent way Python access attributes of a class with the Descriptor protocol -

Just make your field classes have a __get__, __set__ and __delete__ method as described in https://docs.python.org/2/howto/descriptor.html -- And be sure that all you classes have object as the base class, otherwise they inherit from old-style classes, that only exist in Python 2 for compatibility reasons, and are deprecated since Python 2.2 (and ignore completely the descriptor protocol)

jsbueno
  • 99,910
  • 10
  • 151
  • 209