difference between `x in list` and `list.index(x)` for instances of anew-style class

Discussion in 'Python' started by Riccardo Murri, Dec 28, 2007.

  1. Hello,

    I have some code that stops when trying to find a graph in a list of
    similar graphs::

    (Pydb) list
    110 try:
    111 canonical = self.base[self.base.index(graph)]
    112 except ValueError:
    113 raise ValueError, \
    114 "Cannot find canonical representative for graph `%s`." \
    115 -> % (repr(graph),)
    116
    ....

    The list `self.base` contains "canonical" forms of the graphs and the
    `graph` object must compare equal to some item of the list, which
    indeed it does::

    (Pydb) p graph == self.base[27]
    True

    (Pydb) p graph in self.base
    True

    However, I cannot directly get the index of the canonical graph (the
    number "27" above was found by manual inspection)::

    (Pydb) self.base.index(graph)
    *** ValueError: list.index(x): x not in list

    All graphs are instances of a `Graph` new-style class that implements
    comparison operators `__eq__` and `__ne__`, but no other rich-compare
    stuff.

    I'm using Python 2.5::

    Python 2.5 (release25-maint, Dec 9 2006, 16:17:58)
    [GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-20)] on linux2

    So my question is: what are the implementation differences between `x
    in list` and `list.index(x)` and why can one report that an item is in
    the list while the other cannot find its index? Should I add
    something to the `Graph` class so that `index` works?

    Thanks for any hint!


    --
    Riccardo Murri, via Galeazzo Alessi 61, 00176 Roma
     
    Riccardo Murri, Dec 28, 2007
    #1
    1. Advertising

  2. Riccardo Murri

    Guest

    Re: difference between `x in list` and `list.index(x)` for instancesof a new-style class

    On 28 dic, 20:12, Riccardo Murri <> wrote:

    > The list `self.base` contains "canonical" forms of the graphs and the
    > `graph` object must compare equal to some item of the list, which
    > indeed it does::
    >
    >   (Pydb) p graph == self.base[27]  
    >   True
    >
    >   (Pydb) p graph in self.base
    >   True
    >
    > However, I cannot directly get the index of the canonical graph (the
    > number "27" above was found by manual inspection)::
    >
    >   (Pydb) self.base.index(graph)
    >   *** ValueError: list.index(x): x not in list
    >
    > All graphs are instances of a `Graph` new-style class that implements
    > comparison operators `__eq__` and `__ne__`, but no other rich-compare
    > stuff.
    >
    > I'm using Python 2.5::
    >
    >   Python 2.5 (release25-maint, Dec  9 2006, 16:17:58)
    >   [GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-20)] on linux2
    >
    > So my question is: what are the implementation differences between `x
    > in list` and `list.index(x)` and why can one report that an item is in
    > the list while the other cannot find its index?  Should I add
    > something to the `Graph` class so that `index` works?


    (I've checked on 2.5.1 but I don't see any relevant differences with
    the 2.5 version). Looking at the source for both methods, they only
    use the __eq__ operator, but there is a slight difference: while one
    evaluates list==x, the other reverses the operands. If your __eq__
    is not reflexive, that could explain the difference.

    class Graph(object):
    def __init__(self, *items):
    self.items = items

    def __eq__(self, other):
    if len(self.items)>len(other.items): return False
    return self.items == other.items[:len(self.items)]

    py> List = [Graph(1,2,3), Graph(4,5,6), Graph(1,2,3,4)]
    py> g = Graph(1,2)
    py> g in List
    True
    py> List.index(g)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    ValueError: list.index(x): x not in list
    py> List[0]==g
    False
    py> g==List[0]
    True

    In your example, see if self.base[27]==graph is still True.

    --
    Gabriel Genellina
     
    , Dec 29, 2007
    #2
    1. Advertising

  3. Re: difference between `x in list` and `list.index(x)` for instancesof a new-style class

    writes:

    > On 28 dic, 20:12, Riccardo Murri <> wrote:
    >
    >> The list `self.base` contains "canonical" forms of the graphs and the
    >> `graph` object must compare equal to some item of the list, which
    >> indeed it does::
    >>
    >>   (Pydb) p graph == self.base[27]  
    >>   True
    >>
    >>   (Pydb) p graph in self.base
    >>   True
    >>
    >> However, I cannot directly get the index of the canonical graph (the
    >> number "27" above was found by manual inspection)::
    >>
    >>   (Pydb) self.base.index(graph)
    >>   *** ValueError: list.index(x): x not in list
    >>
    >> All graphs are instances of a `Graph` new-style class that implements
    >> comparison operators `__eq__` and `__ne__`, but no other rich-compare
    >> stuff.
    >>
    >> I'm using Python 2.5::
    >>
    >>   Python 2.5 (release25-maint, Dec  9 2006, 16:17:58)
    >>   [GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-20)] on linux2
    >>
    >> So my question is: what are the implementation differences between `x
    >> in list` and `list.index(x)` and why can one report that an item is in
    >> the list while the other cannot find its index?  Should I add
    >> something to the `Graph` class so that `index` works?

    >
    > (I've checked on 2.5.1 but I don't see any relevant differences with
    > the 2.5 version). Looking at the source for both methods, they only
    > use the __eq__ operator, but there is a slight difference: while one
    > evaluates list==x, the other reverses the operands. If your __eq__
    > is not reflexive, that could explain the difference.
    >


    That was indeed the reason: a bug in Graph.__eq__ broke reflexivity in
    certain cases.

    Thank you very much!!

    --
    Riccardo Murri, via Galeazzo Alessi 61, 00176 Roma
     
    Riccardo Murri, Dec 30, 2007
    #3
  4. Re: difference between `x in list` and `list.index(x)` for instancesof a new-style class

    On 30 dic, 06:24, Riccardo Murri <> wrote:
    > writes:
    >
    > >>   (Pydb) p graph == self.base[27]  
    > >>   True
    > >>   (Pydb) p graph in self.base
    > >>   True
    > >>   (Pydb) self.base.index(graph)
    > >>   *** ValueError: list.index(x): x not in list


    > > Looking at the source for both methods, they only
    > > use the __eq__ operator, but there is a slight difference: while one
    > > evaluates list==x, the other reverses the operands. If your __eq__
    > > is not reflexive, that could explain the difference.

    >
    > That was indeed the reason: a bug in Graph.__eq__ broke reflexivity in
    > certain cases.


    Combined with some other WTF bugs I've found at work, lately I feel
    more like a detective than a software developer :)

    --
    Gabriel Genellina
     
    Gabriel Genellina, Dec 30, 2007
    #4
    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. Nir

    Create anew session .

    Nir, May 23, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    411
  2. jakk
    Replies:
    4
    Views:
    12,511
  3. John Wohlbier
    Replies:
    2
    Views:
    391
    Josiah Carlson
    Feb 22, 2004
  4. Garg
    Replies:
    5
    Views:
    286
    Andrew Thompson
    Dec 11, 2006
  5. Ravi
    Replies:
    5
    Views:
    266
    James Kanze
    Feb 17, 2009
Loading...

Share This Page