Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use __setattr__ correctly, avoiding infinite recursion

I want to define a class containing read and write methods, which can be called as follows:

instance.read instance.write instance.device.read instance.device.write 

To not use interlaced classes, my idea was to overwrite the __getattr__ and __setattr__ methods and to check, if the given name is device to redirect the return to self. But I encountered a problem giving infinite recursions. The example code is as follows:

class MyTest(object):     def __init__(self, x):         self.x = x      def __setattr__(self, name, value):         if name=="device":             print "device test"         else:             setattr(self, name, value)  test = MyTest(1) 

As in __init__ the code tried to create a new attribute x, it calls __setattr__, which again calls __setattr__ and so on. How do I need to change this code, that, in this case, a new attribute x of self is created, holding the value 1?

Or is there any better way to handle calls like instance.device.read to be 'mapped' to instance.read?

As there are always questions about the why: I need to create abstractions of xmlrpc calls, for which very easy methods like myxmlrpc.instance,device.read and similar can be created. I need to 'mock' this up to mimic such multi-dot-method calls.

like image 821
Alex Avatar asked Jun 10 '13 08:06

Alex


People also ask

What is __ Setattr __ in Python?

Python's magic method __setattr__() implements the built-in setattr() function that takes an object and an attribute name as arguments and removes the attribute from the object. We call this a “Dunder Method” for “Double Underscore Method” (also called “magic method”).

Is Setattr () used for?

Python setattr() Python setattr() function is used to assign a new value to the attribute of an object/instance. Setattr in python sets a new specified value argument to the specified attribute name of a class/function's defined object.

What is use of Setattr () method in inheritance?

What is the use of the setattr() method in inheritance? The use case of setattr() in inheritance is the same, i.e., to assign value to the attributes of an object.

What is setattr () method in Python?

Python setattr () method Difficulty Level : Basic Last Updated : 04 Dec, 2020 setattr () is used to assign the object attribute its value.

How to initialize a new object attribute using setattr in Python?

setattr () can be used to initialize a new object attribute. Let’s take a simple dictionary “my_dict” which has the Name, Rank, and Subject as my Keys and they have the corresponding values as Geeks, 1223, Python. We are calling a function here Dict2Class which takes our dictionary as an input and converts it to class.

What is the difference between valval and setattr in Python?

val : value with which variable is to be assigned. setattr () can be used to assign None to any object attribute. setattr () can be used to initialize a new object attribute. Let’s take a simple dictionary “my_dict” which has the Name, Rank, and Subject as my Keys and they have the corresponding values as Geeks, 1223, Python.

What is the use of setattr?

setattr() is used to assign the object attribute its value. Apart from ways to assign values to class variables, through constructors and object functions, this method gives you an alternative way to assign value. Parameters : obj : Object whose which attribute is to be assigned.


2 Answers

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 
like image 125
Bakuriu Avatar answered Sep 26 '22 15:09

Bakuriu


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 
like image 21
Vindolin Avatar answered Sep 24 '22 15:09

Vindolin