Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between __set__ and __setattr__ in Python and when should which be used?

As the title says.

Coming from Java im used to:

private int A;

public void setA(int A) {
    this.A = A;
}

public int getA() {
    return this.A
}

How do I do that (if I need to) in Python. And if one of __setattr__ or __set__ is used for this, what is the other one used for?

Edit: I feel I need to clarify. I know that in Python one doe's not create setters and getters before they are needed.

Lets say I want to do something like this:

public void setA(int A) {
    update_stuff(A);
    and_calculate_some_thing(A);
    this.A = A;
}

What is the "pythonic" way to implement this?

like image 486
evading Avatar asked May 22 '12 17:05

evading


1 Answers

In python, something like this should be implemented using a property (and then only when they do something useful).

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

    @property
    def x(self):
        return self._x

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

In this example, it would be better to just do (as pointed out by Edward):

class Foo(object):
     def __init__(self):
         self.x = None

since our getter/setter methods don't actually do anything ... However, properties become very useful when the setter/getter actually does something more than just assign/return an attribute's value.

It could also be implemented using __setattr__/__getattr__ (but it shouldn't be implemented this way as it quickly becomes cumbersome if your class has more than 1 property. I would also guess that doing it this way would be slower than using properties):

class Foo(object):
    def __init__(self):
        self._x = None
    def __setattr__(self,attr,obj):
        if(attr == 'x'):
            object.__setattr__(self,'_x',obj)
        else:
            object.__setattr__(self,attr,obj)

    def __getattr__(self,attr):
        if(attr == 'x'):
            return object.__getattr__(self,'_x')
        else:
            return object.__getattr__(self,attr)

In terms of what __setattr__ and __getattr__ actually do... __setattr__/__getattr__ are what are called when you do something like:

myclassinstance = MyClass()
myclassinstance.x = 'foo'  #translates to MyClass.__setattr__(myclassinstance,'x','foo')
bar = myclassinstance.x    #translates to bar=MyClass.__getattr__(myclassinstance,'x')

As for __get__ and __set__: previous posts have discussed that quite nicely.

Note that in python there is no such thing as private variables. In general, in a class member is prefixed with an underscore, you shouldn't mess with it (unless you know what you're doing of course). If it's prefixed with 2 underscores, it will invoke name-mangling which makes it harder to access outside the class. This is used to prevent namespace clashes in inheritance (and those variables are generally also not to be messed with).

like image 165
mgilson Avatar answered Sep 24 '22 17:09

mgilson