18

I know that you can't call object.__setattr__ on objects not inherited from object, but is there anything else that is different between the two? I'm working in Python 2.6, if this matters.

paper.cut
  • 235
  • 1
  • 3
  • 7
  • 1
    `setattr` is something that you call on another object, `__setattr__()` is something that you implement on your own object. – David Heffernan Sep 26 '11 at 18:03
  • 1
    `setattr(obj, attr, value)` just calls `obj.__setattr__(attr, value)`, at least for new-style classes. – agf Sep 26 '11 at 18:05

1 Answers1

18

Reading this question again I misunderstood what @paper.cut was asking about: the difference between classic classes and new-style classes (not an issue in Python 3+). I do not know the answer to that.


Original Answer*

setattr(instance, name, value) is syntactic sugar for instance.__setattr__(name, value)**.

You would only need to call object.__setattr__(...) inside a class definition, and then only if directly subclassing object -- if you were subclassing something else, Spam for example, then you should either use super() to get the next item in the heirarchy, or call Spam.__setattr__(...) -- this way you don't risk missing behavior that super-classes have defined by skipping over them directly to object.


* applies to Python 3.0+ classes and 2.x new-style classes


**There are two instances where setattr(x, ...) and x.__setattr__(...) are not the same:

  • x itself has a __setattr__ in it's private dictionary (so x.__dict__[__setattr__] = ... (this is almost certainly an error)

  • x.__class__ has a __getattribute__ method -- because __getattribute__ intercepts every lookup, even when the method/attribute exists

NB These two caveats apply to every syntactic sugar shortcut:

  • setattr
  • getattr
  • len
  • bool
  • hash
  • etc
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • 3
    Thanks, that explains it. The code is probably using `object.__setattr__` for the exact purpose of skipping the superclass's __setattr__. – paper.cut Sep 27 '11 at 20:56
  • _"setattr(instance, name, value) is syntactic sugar for instance.__setattr__(name, value)"_ - is it really? I vaguely remember that some types don't have `__getattr__` but getting attributes works for them regardless. Isn't it the same here? – ivan_pozdeev Apr 29 '17 at 06:09
  • For a subtle caveat, see my question: https://stackoverflow.com/questions/56144186 – Maxpm May 17 '19 at 04:18
  • @Maxpm: Your question deals with `super`, which should only be used as documented. – Ethan Furman May 17 '19 at 06:13