26

I don't know for why using __setattr__ instead simple referencing like x.a=1.

I understand this example:

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0


x=Rectangle()
x.width=20
x.__setattr__('height',30)
setattr(x,'width',99)

but don't get why using code depending on string ('height').

Could you explain me what are advantages of __setattr__ ?

wRAR
  • 25,009
  • 4
  • 84
  • 97
user278618
  • 19,306
  • 42
  • 126
  • 196

7 Answers7

34

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".

AJ.
  • 27,586
  • 18
  • 84
  • 94
18

__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)
pajton
  • 15,828
  • 8
  • 54
  • 65
  • 3
    Does the latter construct have any advance over `self.__dict__.update(kwargs)`? – gerrit Mar 05 '14 at 20:32
  • 6
    Yes it does. Using `setattr` goes through custom `__setattr__` if defined. Please note that custom `__setattr__` doesn't have to touch `__dict__` at all (it's common to use `__setattr__` for some dynamic attribute lookup, proxy etc.). – pajton Mar 05 '14 at 21:52
8

I can envision an application where, for example, you override __setattr__ and __getattr__ to provide object-like access to some other data structure that isn't kept in memory. For example, you could create an object where foo.CustomerName = "John" updated the CustomerName column in a database row pointed to by foo to contain the value "John". I.e., foo.__setattr__ would use the attribute name and value to construct a command to update a database on disk. I'd hate to have to write such a thing, but it would be possible.

Peter Milley
  • 2,768
  • 19
  • 18
  • 3
    This is exactly how I've used `__setattr__` in the past. It's not for the feint of heart, and I recommend rigorous testing (even `test-driven development`) to anyone who needs this sort of special functionality. – Kyle Wild Apr 22 '11 at 15:03
2

The first use of __setattr__ is to be overwritten in a class definition.

class Foo ( object ) :

    def __init__ ( self ) :
        self.x = 'looser'

    def __setattr__ ( self, name, value ) :
        if name == 'x' :
            print( 'Hello, {} !'.format( value ) )
            self.x = value

Problem, Foo() will print an infinite sequence of :

'Hello, looser !'

There comes the second use which is that, when you're doing that, you can call setattr from the parent class (object by default) to avoid infite recursion :

class Foo ( object ) :

    def __setattr__ ( self, name, value ) :
        self.bar( name, value )
        object.__setattr__( self, name, value )

    def bar ( self, name, value ) :
        print( 'Setting {} to {}.'.format( name, value ) )

And therefore :

f = Foo()

>> 'Hello, winner !'

f.x

>> 'winner'
Thrastylon
  • 853
  • 7
  • 20
2

Note that __xxx__ are operator overloading methods of the class and as such should only be used in special situations and not in cases as in your example.

For example, __setattr__ intercepts all attribute assignments and can be used to change the behaviour of your class when a value is assigned to an attribute.

Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
joaquin
  • 82,968
  • 29
  • 138
  • 152
1

the __setattr__ can be used to reflection, where an propperty on the object Rectangle can be created at runtime, there are more about it on http://en.wikipedia.org/wiki/Reflection_%28computer_science%29

class Rectangle:
    def __init__(self):
        #... code ...

x = Rectangle()
#x.__setattr__('newProperty',30)      Edited after comment
setattr(x, 'newProperty', 30)
print x.newProperty #>>> 30
joaquin
  • 82,968
  • 29
  • 138
  • 152
aweis
  • 5,350
  • 4
  • 30
  • 46
  • 3
    Apart from the fact that that's a horrible idea for most puposes (notable exception: some metaprogramming): Why not just use the built-in `setattr`? –  Apr 22 '11 at 11:42
0
class Name(object):
    pass

obj=Name()

#just i have created object two way 
#first

obj.a="first"
print obj.a

#answer= "first"
#second

obj.__setattr__('b','second')
print obj.a
#answer= "second"
  • 1
    Hi and welcome to stack overflow. I would recommend you to provide more details on how this code is helping the issue. – Wtower Jun 13 '15 at 06:36