This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: object.__setattr__ or super(...).__setattr__?
Type: enhancement Stage:
Components: Documentation Versions: Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: b9, docs@python, rhettinger
Priority: normal Keywords:

Created on 2014-06-20 10:02 by b9, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg221082 - (view) Author: Vincent Besanceney (b9) Date: 2014-06-20 10:02
In: https://docs.python.org/2.7/reference/datamodel.html#customizing-attribute-access

Regarding the description of __setattr__ method: "For new-style classes, rather than accessing the instance dictionary, it should call the base class method with the same name, for example, object.__setattr__(self, name, value)."

Wouldn't it be more consistent for new-style classes, instead of calling "object.__setattr__(self, name, value)", to call "super(<ClassName>, self).__setattr__(name, value)"?
msg221144 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2014-06-21 02:14
> Wouldn't it be more consistent for new-style classes,
> instead of calling "object.__setattr__(self, name, value)",
> to call "super(<ClassName>, self).__setattr__(name, value)"?

That's not always the right thing to do.  Calling object.__setattr__ gives a known, guaranteed behavior.   Using super however relies on an MRO calculation that may send the super call outside the inheritance tree to a methods that wasn't expecting to be called. 

Put another way, super was designed for cooperative multiple inheritance with implies an element of coordinated cooperation that isn't always present.

I think the current advice should stand.  We aren't advising people to always use super instead of calling a parent class method directly.  Part of the reason is that super can be much trickier that people expect.

Also, in Python 2.7 super() doesn't have the same magical but clean invocation it has in Python 3.  The two argument form isn't as elegant looking or as easy to get right.
msg221159 - (view) Author: Vincent Besanceney (b9) Date: 2014-06-21 07:41
If I understand it right, in a simple case like this:

  class Foo(object):

    def __setattr__(self, name, value):
      # some logic, then...
      super(Foo, self).__setattr__(name, value)

calling super is equivalent to calling object.__setattr__, but doesn't have any added-value since there's no cooperative multiple inheritance involved, in that case we are better off calling the parent class method directly.

If Foo evolves to have multiple ancestors, object has a __setattr__ method and that object is always the last class in the MRO chain, so any sequence of calls to super(..).__setattr__ is guaranteed to end with a call to object.__setattr__ method (assuming ancestors __setattr__ method, if any, calls super as well), and that may be what we want, i.e. to also benefit from an ancestor __setattr__ method.

Hmm, this last point may be too specific if not out of scope in regards to the documentation. Falling back to the original need, from the documentation "If __setattr__() wants to assign to an instance attribute...", so as you said, "calling object.__setattr__ gives a known, guaranteed behavior".
msg221181 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2014-06-21 16:18
> If I understand it right, in a simple case like this: 
 ...
> calling super is equivalent to calling object.__setattr__,

It is not equivalent.  Instances of Foo() would behave equivalently but it might do something different for subclasses of Foo.  If you're interested in learning more about super(), have a look at:  http://rhettinger.wordpress.com/2011/05/26/super-considered-super/

In the meantime, I'm closing this because we do not make that blanket advice to always use super() instead of a direct call to a parent.  Sometimes you want one and sometimes you want the other depending on what you're trying to do.
History
Date User Action Args
2022-04-11 14:58:05adminsetgithub: 66013
2014-06-21 16:18:47rhettingersetstatus: open -> closed
resolution: not a bug
messages: + msg221181
2014-06-21 07:41:06b9setmessages: + msg221159
2014-06-21 02:14:15rhettingersetassignee: docs@python -> rhettinger

messages: + msg221144
nosy: + rhettinger
2014-06-20 10:02:12b9create