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