Re [Python-Dev] object equality vs identity, in and dicts idioms and speed

Martin v. Loewis martin@v.loewis.de
Fri, 4 Jan 2002 22:39:49 +0100


> I'm slightly confuzzled here (no surprise given how little Java I know).
> How does Jython know which Java class instance to refer to if there's
> no mapping?  

I understand Samuele was talking about mapping in the Python sense
(existance of dictionary-style containers); he also mentioned that
Jython creates a Python wrapper object for each "foreign" Java object.

Creating wrapper objects immediately raises the issue of identity: If
you get the very same Java objects two times, do you want to use the
same wrapper object? If yes, how do you find out that you already have
a wrapper object. This is where the mapping comes into play.

If no, how do you implement "is"? Well, that's easy:

  def is(o1, o2):
    if o1 instanceof wrapper:
      if not o2 instanceof wrapper: return false
      return o1.wrapped identical_to o2.wrapped
    return o1 identical_to o2

Now, how do you implement id()? More tricky: Tim suggests you bump a
counter every time you create a Python object. Works fine for "true"
python objects:

  def id(o):
    return o.countervalue

Doesn't work as well for wrapper objects: When should you bump the
counter? When you create the wrapper? But then there may be two
wrappers with different ids refering to the very same object, so you'd
have 'o1 is o2 and id(o1) <> id(o2)' which clearly is a no-no.

> If there is a mapping, how does it slow things down to create an id
> every time a map gets created?

You can do it like this:

map = {}

def wrap(java.lang.Object o):
  try:
    return map[o]
  except KeyError:
    map[o] = res = wrapper(o, new_id())
    return res

That requires a map lookup every time a wrapper is created; clearly
undesirable. I think Samuele had something in mind like:

map = {}

def wrap(java.lang.Object o):
  return wrapper(o, None)

def id(o):
  if not o instanceof wrapper:
    return o.countervalue
  if o.countervalue:
    return o.countervalue
  try:
    o.countervalue = map[o.wrapped]
  except KeyError:
    o.countervalue = map[o.wrapped] = new_id()
  return o.countervalue

So you'd take the cost of a map lookup only if somebody accesses the
id of an object.

That would still mean that all Java objects whose Python id() was ever
computed would live in the dictionary forever; there you need a
WeakkeyDictionary.

Regards,
Martin