Reputation: 3090
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?
Upvotes: 14
Views: 11987
Reputation: 310187
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).
Upvotes: 18
Reputation: 215039
Assume you've got class Master
with an attribute x
which is of class Slave
and you want some code to be executed when you assign something to x
as in some_master.x = foo
. Where will this code be located? It can be in the class Master
, in which case you use __setattr__
. It can be also in the class Slave
, so that it has a control on what is being assigned. In this case, you make Slave
a descriptor and use __set__
.
Examples:
>>> class Master(object):
... def __setattr__(self, name, val):
... print "run code in Master: %s" % val
...
>>> a = Master()
>>> a.x = 123
run code in Master: 123
compare to this:
>>> class Slave(object):
... def __set__(self, obj, val):
... print "run code in Slave: %s" % val
...
>>> class Master2(object):
... x = Slave()
...
>>> b = Master2()
>>> b.x = 345
run code in Slave: 345
To answer the question which one is more pythonic, I'd say neither. If you need to actually do something, make it a function. Explicit > implicit.
def update_param(a):
update_stuff(a)
and_calculate_some_thing(a)
self.a = a
Upvotes: 5
Reputation: 15944
If the getter/setter are really as trivial as that, then you shouldn't even bother with them: just use an instance variable. If you do need a getter/setter that does something interesting, then you should switch to a property, as mgilson described. Note that you can change from an instance variable to a property without anything that uses your code noticing the difference. I.e., start with:
class Foo(object):
def __init__(self):
self.x = None
And only change to the property-based accessors mgilson described if/when it turns out you need something interesting to happen when you get/set the attribute.
Upvotes: 8
Reputation: 799330
__set__()
is used in descriptors when the descriptor is assigned to. __setattr__()
is used when binding to an attribute of an object. Unless you're creating a descriptor, you won't use __set__()
.
Upvotes: 9