Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling getter and setter for a python's class

Tags:

python

Consider the following class :

class Token:
    def __init__(self):
        self.d_dict = {}

    def __setattr__(self, s_name, value):
        self.d_dict[s_name] = value

    def __getattr__(self, s_name):
        if s_name in self.d_dict.keys():
            return self.d_dict[s_name]
        else:
            raise AttributeError('No attribute {0} found !'.format(s_name))

In my code Token have some other function (like get_all() wich return d_dict, has(s_name) which tell me if my token has a particular attribute).

Anyway, I think their is a flaw in my plan since it don't work : when I create a new instance, python try to call __setattr__('d_dict', '{}').

How can I achieve a similar behaviour (maybe in a more pythonic way ?) without having to write something like Token.set(name, value) and get(name) each I want to set or get an attribute for a token.

Critics about design flaw and/or stupidity welcome :)

Thank !

like image 911
thomas Avatar asked Aug 06 '09 21:08

thomas


3 Answers

You need to special-case d_dict.

Although of course, in the above code, all you do is replicate what any object does with __dict__ already, so it's pretty pointless. Do I guess correctly if you intended to special case some attributes and actally use methods for those?

In that case, you can use properties.

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x
like image 92
Lennart Regebro Avatar answered Oct 08 '22 15:10

Lennart Regebro


The special-casing of __dict__ works like this:

def __init__(self):
    self.__dict__['d_dict'] = {}

There is no need to use a new-style class for that.

like image 44
Martin v. Löwis Avatar answered Oct 08 '22 17:10

Martin v. Löwis


A solution, not very pythonic but works. As Lennart Regebro pointed, you have to use a special case for d_dict.

class Token(object):

    def __init__(self):
        super(Token,self).__setattr__('d_dict', {})

    def __getattr__(self,name):
        return self.a[name]

    def __setattr__(self,name,value):
        self.a[name] = value

You need to use new style classes.

like image 37
Ferran Avatar answered Oct 08 '22 16:10

Ferran