The Python docs say all that needs to be said, as far as I can see.
Answer from Chris Morgan on Stack Overflow
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.
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()
attributes - What is the difference between __set__ and __setattr__ in Python and when should which be used? - Stack Overflow
setter - Why to use __setattr__ in python? - Stack Overflow
Why used setattr/getattr instead of writing my own methods?
Why `self.__setattr__(attr, value)` trigger `__getattribute__`?
Videos
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).
__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__().
You don't call it yourself. Period. If you need to use a string because you don't know the name beforehand (very bad idea in 99% of all cases where one might think they need this, nearly always a dict or list is a better/saner choice), you use the built-in setattr function.
However, it is called for you - when you do a.x = ..., that's done as a.__setattr__('x', ...) (this is propably an oversimplification). And some objects overload it to allow some trickery, e.g. to emulate immutability. See the documentation of "special methods".
__setattr__ is a class method that is called by setattr builtin method. That is, if __setattr__ is defined in given class. Most often you do not declare your own version of __setattr__ so I assume you are asking of what use is the setattr method.
Suppose you have a var with the name of the attribute you want to set instead of just knowing the name:
class A(object):
def doSth(self, name, val):
setattr(self, name, val)
impossible to do with self.name = val
Also, a common usage is with keyword args:
class A(object):
def __init__(self, *args, **kwargs):
for k,v in kwargs.items():
setattr(self, k, v)
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)}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