Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call methods on Python class descriptor objects?

I created a class String() with __get__(), __set__(), and a method to_db(); however, when I do name = String(), I can't do self.name.to_db() because it's calling to_db() on the value returned by __get__(), not the object "name".

class String(object):

    def __init__(self, value=None):
        if value:
            self.value = str(value)

    def __get__(self, instance, owner):
        return self.value

    def __set__(self, instance, value):
        self.value = str(value)

    def to_db(self):
        return {'type':'string', 'value': self.value}

class Example(object):

    name = String()
    age = Integer()

    def __init__(self,name,age):
        self.name = name
        self.age = age

    def save():
        data = dict(name=self.name.to_db(), age=self.age.to_db())
        db.save(data)

One way to deal with this is to not call self.name.to_db() directly and instead set a flag in instance and create a conditional in __get__() to check for it and call to_db() if it's True, but this seems kludgy. Is there a better way?

Also, I'm new to descriptors -- what are the pros/cons of using instance and/or instance.__dict__ to store state vs storing it in self?

like image 667
espeed Avatar asked May 16 '11 21:05

espeed


1 Answers

It's pretty easy - just have your descriptor return a subclass of string with the extra method(s) you want.

def __get__(self, instance, owner):
    class TaggedString(str):
        def to_db(self):
            return {'type':'string', 'value': self}
    return TaggedString(self.value)`
like image 154
Jeff Rush Avatar answered Nov 05 '22 16:11

Jeff Rush