27

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__ ?

7 Answers 7

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

Sign up to request clarification or add additional context in comments.

Comments

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)

2 Comments

Does the latter construct have any advance over self.__dict__.update(kwargs)?
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.).
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.

1 Comment

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

Comments

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.

Comments

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

1 Comment

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?
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 Comment

Hi and welcome to stack overflow. I would recommend you to provide more details on how this code is helping the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.