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).
Answer from mgilson on Stack OverflowIn 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).
__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__().
Why `self.__setattr__(attr, value)` trigger `__getattribute__`?
Using setattr() in python - Stack Overflow
python - How to use __setattr__ correctly, avoiding infinite recursion - Stack Overflow
__getattr__ Called When Paired with __setattr__
Videos
The Python docs say all that needs to be said, as far as I can see.
setattr(object, name, value)This is the counterpart of
getattr(). The arguments are an object, a string and an arbitrary value. The string may name an existing attribute or a new attribute. The function assigns the value to the attribute, provided the object allows it. For example,setattr(x, 'foobar', 123)is equivalent tox.foobar = 123.
You are setting self.name to the string "get_thing", not the function get_thing.
If you want self.name to be a function, then you should set it to one:
setattr(self, 'name', self.get_thing)
However, that's completely unnecessary for your other code, because you could just call it directly:
value_returned = self.get_thing()
You must call the parent class __setattr__ method:
class MyTest(object):
def __init__(self, x):
self.x = x
def __setattr__(self, name, value):
if name=="device":
print "device test"
else:
super(MyTest, self).__setattr__(name, value)
# in python3+ you can omit the arguments to super:
#super().__setattr__(name, value)
Regarding the best-practice, since you plan to use this via xml-rpc I think this is probably better done inside the _dispatch method.
A quick and dirty way is to simply do:
class My(object):
def __init__(self):
self.device = self
Or you can modify self.__dict__ from inside __setattr__():
class SomeClass(object):
def __setattr__(self, name, value):
print(name, value)
self.__dict__[name] = value
def __init__(self, attr1, attr2):
self.attr1 = attr1
self.attr2 = attr2
sc = SomeClass(attr1=1, attr2=2)
sc.attr1 = 3
Hello fellow pythoners!
I was introduced to the built-in function setattr() and getattr() functions today in regards to classes and started to question why I would want to use these functions instead of writing my own get_attribute and set_attribute methods.
So yeah, why? All my searches just gave me explanations as to how they're used, not why to use it instead of what I was taught back in school.
Is writing my own methods just a translation to how to handle this from someone who came from a language such as java or C# to setting and getting attributes?
Edit: Code example below
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def get_name(self):
return self.name
def get_grade(self):
return self.grade
def set_name(self, name):
self.name = name
def set_grade(self, grade):
self.grade = grade
class Person:
def __init__(self, name, addr):
self.name = name
self.address = addr
if __name__ == "__main__":
george = Student("George", "B")
jessica = Person("Jessica", "221B Baker Steet")
print(f"{george.get_name()} has a {george.get_grade()} in English.")
george.set_grade("A")
print(f"{george.get_name()} now has a {george.get_grade()} in English")
print(f"{getattr(jessica, name)} lives on {getattr(jessica, address)}.")
setattr(jessica, address, "Abbey Road 5")
print(f"{getattr(jessica, name)} now lives on {getattr(jessica, address)}