What method does slice notation call?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Robert Brewer

    What method does slice notation call?

    >>> class A(types.DictTyp e):
    .... def __getitem__(sel f, key):
    .... return types.DictType. __getitem__(sel f, key)
    .... [color=blue][color=green][color=darkred]
    >>> a = A()
    >>> a[0] = 3
    >>> a.__getitem__ = lambda x: "w00t"
    >>> a.__getitem__(0 )[/color][/color][/color]
    'w00t'[color=blue][color=green][color=darkred]
    >>> a[/color][/color][/color]
    {0: 3}[color=blue][color=green][color=darkred]
    >>> a[0][/color][/color][/color]
    3

    Can anyone tell me why a[0] doesn't return "w00t", like I thought it
    would? What method is a[0] calling? Is there a way to override it?


    Robert Brewer
    MIS
    Amor Ministries
    fumanchu@amor.o rg

  • Peter Otten

    #2
    Re: What method does slice notation call?

    Robert Brewer wrote:
    [color=blue][color=green][color=darkred]
    >>>> class A(types.DictTyp e):[/color][/color]
    > ... def __getitem__(sel f, key):
    > ... return types.DictType. __getitem__(sel f, key)
    > ...[color=green][color=darkred]
    >>>> a = A()
    >>>> a[0] = 3
    >>>> a.__getitem__ = lambda x: "w00t"
    >>>> a.__getitem__(0 )[/color][/color]
    > 'w00t'[color=green][color=darkred]
    >>>> a[/color][/color]
    > {0: 3}[color=green][color=darkred]
    >>>> a[0][/color][/color]
    > 3
    >
    > Can anyone tell me why a[0] doesn't return "w00t", like I thought it
    > would? What method is a[0] calling? Is there a way to override it?[/color]

    The special methods are somewhat reluctant when you try to override them on
    the instance level. Here are two ways using brute force.
    (There are probably more elegant ways that involve metaclasses...)

    Peter

    <code>
    import types

    # implement __getitem__() in terms of a "normal" method
    # that can be overridden on a per instance basis
    class A(types.DictTyp e):
    def getitem(self, key):
    return types.DictType. __getitem__(sel f, key)
    def __getitem__(sel f, key):
    return self.getitem(ke y)

    a = A()
    a.getitem = lambda key: "if you must"

    print a["dummy"]

    # just subclassing...
    class B(A):
    __getitem__ = lambda self, key: "there you are"

    b = B()
    print b["dummy"]
    </code>

    Comment

    • Alex Martelli

      #3
      Re: What method does slice notation call?

      Robert Brewer wrote:
      [color=blue][color=green][color=darkred]
      >>>> class A(types.DictTyp e):[/color][/color]
      > ... def __getitem__(sel f, key):
      > ... return types.DictType. __getitem__(sel f, key)
      > ...[color=green][color=darkred]
      >>>> a = A()
      >>>> a[0] = 3
      >>>> a.__getitem__ = lambda x: "w00t"
      >>>> a.__getitem__(0 )[/color][/color]
      > 'w00t'[color=green][color=darkred]
      >>>> a[/color][/color]
      > {0: 3}[color=green][color=darkred]
      >>>> a[0][/color][/color]
      > 3
      >
      > Can anyone tell me why a[0] doesn't return "w00t", like I thought it
      > would? What method is a[0] calling? Is there a way to override it?[/color]

      For all except "classic classes" (which have to do lots of hacking
      behind the scenes for backwards compatibility, sigh), a[0] means
      roughly the equivalent of:

      getattr(type(a) , '__getitem__')( a, 0)

      so, if you want to have a[0] invoke something different, you must
      change type(a) accordingly, e.g.:

      def changeindexing( a, newgetitem):
      class x(type(a)):
      __getitem__ = newgetitem
      a.__class__ = x

      so, for example:

      def changeindexing( a, newgetitem):
      class x(type(a)):
      __getitem__ = newgetitem
      a.__class__ = x

      class A(dict):
      def __getitem__(sel f, key):
      return dict.__getitem_ _(self, key)

      a = A()
      a[0] = 3
      a.__getitem__ = lambda x: "w00t"
      print a.__getitem__(0 )
      print a
      print a[0]

      changeindexing( a, lambda self, x: 'blaap')

      print a.__getitem__(0 )
      print a
      print a[0]

      prints:

      w00t
      {0: 3}
      3
      w00t
      {0: 3}
      blaap


      Note that the function you pass to changeindexing does need a 'self', just
      like any other method. If you don't want that, you can use a staticmethod,
      of course (but then the function won't have access to the specific instance
      it's being called on).


      Alex

      Comment

      Working...