New style classes and rich comparison

Stian Søiland stain at stud.ntnu.no
Tue Dec 16 23:56:23 EST 2003


Could anyone explain to me why this does not work as intended?

>>> class Oldstyle:
...   pass
...
>>> old = Oldstyle()
>>> old == 1
False
>>> old.__eq__ = lambda x: True
>>> old == 1
True

Nice and fine.


>>> newbie = Newstyle()
>>> newbie == 1
False
>>> newbie.__eq__ = lambda x: True
>>> newbie == 1
False

Doesn't work!


It seems that __eq__ is fetched directly from newbie's class, not from
newbie.

>>> Newstyle.__eq__ = lambda self, x: True
>>> newbie == 1
True

Adding a method __getattribute__ that prints the key and then calls
object.__getattribute__ proves this - nothing is printed for comparison.

This goes even for hash():

>>> newbie.__hash__ = lambda x: 1337
>>> hash(newbie)
1077345744
>>> Newstyle.__hash__ = lambda x: 15
>>> hash(newbie)
15



Why is this? Where is this documented? 



Here's my real goal, to create a Dummy class that supports anything:

from dummy.py:

class Dummy(object):
    """An object that can do anything in the world"""
    def __call__(self, *args, **kwargs):
        """Can be called with any kind of parameters, returns
           a new Dummy."""
        return Dummy()
    def __getattribute__(self, key):
        """Any attribute created and stored on demand. All
           attributes are new Dummys."""
        try:
            value = object.__getattribute__(self, key)
        except AttributeError:    
            value = self()
            # remember it to next time! =) 
            setattr(self, key, value)
        return value

This dummy can be used for many things:

>>> from dummy import Dummy
>>> a = Dummy()
>>> a.b
<dummy.Dummy object at 0x81e02dc>
>>> a.b == a.b
1
>>> a.b == a
0
>>> c = a.b.anything(123)
>>> c.dot.something
<dummy.Dummy object at 0x81f3764>


Now the trouble is that __operator__ is not resolved as I would expect. 

>>> a.__add__(a)
<dummy.Dummy object at 0x81ad4dc>
>>> a + a
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  TypeError: unsupported operand types for +: 'Dummy' and 'Dummy'


Why are operators looked up in the class instead of the object? How
can I modify my Dummy class to return 'anything' even directly in the
class?

Ie. what I probably want is something like this (simulated):

    >>> Dummy.asdads
    <dummy.Dummy object at 0x81ad4dc>

That way Dummy.__add__ would return a new Dummy instance, and 
Dummy() + Dummy() would work as expected.

My first attempt was to manually define different __operator__-methods
in the dummy, but this got rather boring. Can I use __metaclass__ or
something?


-- 
Stian Søiland               Being able to break security doesn't make
Trondheim, Norway           you a hacker more than being able to hotwire
http://stain.portveien.to/  cars makes you an automotive engineer. [ESR]




More information about the Python-list mailing list