Instances' __setitem__ methods

Discussion in 'Python' started by Spencer Pearson, Jun 21, 2011.

  1. I was recently trying to implement a dict-like object which would do
    some fancy stuff when it was modified, and found that overriding the
    __setitem__ method of an instance did not act the way I expected. The
    help documentation (from help(dict.__setitem__)) claims that
    "d.__setitem__(k,v)" is equivalent to "d[k]=v", but I've produced this
    code that, on Python 2.6, acts differently in the two cases.

    def print_args( key, value ):
    print "print_args called: key = %s, value = %s" %(key,value)

    class MyDict( dict ):
    def __init__( self ):
    dict.__init__( self )
    self.__setitem__ = print_args

    def __setitem__( self, key, value ):
    print "ModelDict.__setitem__ called"
    dict.__setitem__( self, key, value )

    d = MyDict()

    print "d.__setitem__(0,1):",
    d.__setitem__(0,1)

    print "d[0]=1:",
    d[0]=1


    I would expect the two setitems to both call print_args, but that's
    not what happens. In the first case, it calls print_args, but in the
    second case, the __setitem__ declared in MyDict is called instead.

    The documentation at http://docs.python.org/reference/datamodel.html#specialnames
    says that for new-style classes, "x" is equivalent to
    "type(x).__getitem__(x, i)". I assume that "x=y" has similarly been
    changed to be equivalent to "type(x).__setitem__(x, i, y)", since that
    would produce the results that I'm getting. Is the help documentation
    for dict.__setitem__ just outdated, or am I missing some subtlety
    here?

    Also: when I say "d.f(*args)", am I correct in thinking that d checks
    to see if it has an instance attribute called "f", and if it does,
    calls f(*args); and if it doesn't, checks whether its parent class
    (and then its grandparent, and so on) has a class attribute called
    "f", and if it does, calls f(x, *args)?
     
    Spencer Pearson, Jun 21, 2011
    #1
    1. Advertising

  2. Spencer Pearson

    Ethan Furman Guest

    Spencer Pearson wrote:
    > I was recently trying to implement a dict-like object which would do
    > some fancy stuff when it was modified, and found that overriding the
    > __setitem__ method of an instance did not act the way I expected.


    The __magic__ methods are only looked up on the class, never the instance.

    ~Ethan~
     
    Ethan Furman, Jun 21, 2011
    #2
    1. Advertising

  3. Spencer Pearson

    Chris Rebert Guest

    On Mon, Jun 20, 2011 at 6:42 PM, Spencer Pearson
    <> wrote:
    > I was recently trying to implement a dict-like object which would do
    > some fancy stuff when it was modified, and found that overriding the
    > __setitem__ method of an instance did not act the way I expected. The
    > help documentation (from help(dict.__setitem__)) claims that
    > "d.__setitem__(k,v)" is equivalent to "d[k]=v", but I've produced this
    > code that, on Python 2.6, acts differently in the two cases.


    Technically, the strict equivalence is only one-way, as you've shown;
    but one generally avoids calling the __magic__ methods directly, so
    this subtle distinction is seldom used intentionally.

    <snip>
    > I would expect the two setitems to both call print_args, but that's
    > not what happens. In the first case, it calls print_args, but in the
    > second case, the __setitem__ declared in MyDict is called instead.
    >
    > The documentation at http://docs.python.org/reference/datamodel.html#specialnames
    > says that for new-style classes, "x" is equivalent to
    > "type(x).__getitem__(x, i)". I assume that "x=y" has similarly been
    > changed to be equivalent to "type(x).__setitem__(x, i, y)", since that
    > would produce the results that I'm getting. Is the help documentation
    > for dict.__setitem__ just outdated, or am I missing some subtlety
    > here?


    The sentence of the docs in question begins with "For instance,";
    hence, __setitem__ is just the arbitrarily-chosen example used in this
    part of the docs. But the point applies equally to all the special
    methods. See the very last section of the same webpage:
    http://docs.python.org/reference/datamodel.html#special-method-lookup-for-new-style-classes

    > Also: when I say "d.f(*args)", am I correct in thinking that d checks
    > to see if it has an instance attribute called "f", and if it does,
    > calls f(*args); and if it doesn't, checks whether its parent class
    > (and then its grandparent, and so on) has a class attribute called
    > "f", and if it does, calls f(x, *args)?


    See the first paragraph under the "Classes" entry on
    http://docs.python.org/reference/datamodel.html#objects-values-and-types
    for perfect accuracy.

    Cheers,
    Chris
     
    Chris Rebert, Jun 21, 2011
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ron Garret

    Setdefault bypasses __setitem__

    Ron Garret, Oct 13, 2005, in forum: Python
    Replies:
    9
    Views:
    492
    Fredrik Lundh
    Oct 14, 2005
  2. Almad
    Replies:
    8
    Views:
    420
    Terry Reedy
    Dec 14, 2006
  3. Tor Erik Soenvisen

    str and __setitem__

    Tor Erik Soenvisen, Jan 25, 2007, in forum: Python
    Replies:
    3
    Views:
    281
  4. jeremito
    Replies:
    12
    Views:
    562
    Bruno Desthuilliers
    Feb 7, 2007
  5. luvspython
    Replies:
    2
    Views:
    438
    Eric Snow
    Aug 19, 2011
Loading...

Share This Page