getattr(obj, attr) == getattr(obj, attr) is not true #325

pyjsorg opened this Issue Apr 27, 2012 · 7 comments

1 participant


In python getattr(obj, attr) == getattr(obj, attr) returns true. But in
the conversion to javascript, it returns false. This is because the
javascript version of getattr returns a dynamically created function with
each call. So the second call to getattr(obj, attr) returns a different
object than the first call, and thus are not equal.

Thus the following throws and exception in javascript, but not regular python:
d = dict()
x = [getattr(d, 'update')]
x.remove(getattr(d, 'update'))

Original issue: (April 09, 2010 22:53:55)


From on April 10, 2010 00:03:22:
Attaching a patch to libtest which adds tests for List.remove and getattr.


From on April 25, 2010 12:20:47:
thaank you glenn, this is an excellent find.

there is a way round this, which is to create a cache of getattr'd functions. this
would actually save a lot of time, apart from anything else.


From on May 15, 2010 14:55:47:
Interesting idea. Caching might introduce memory leaks though (I think), or some
extra housekeeping.

class C(object):
def foo(self): return 'foo'

c = C()
a = getattr(c, 'foo') # adds to getattr-cache for object c
del c # should delete from getattr-cache

or, more complicated:
def bar():
c = C()
return getattr(c, 'foo')

a = bar() # object c should be deleted automatically from getattr-cache

We could give every object it's own private getattr_cache (some special attribute on
every object, e.g. getattr_cache).
Advantage: no housekeeping on delete, automatic removal of cache when object is deleted.


From on May 15, 2010 14:59:12:
Hmm, on second thoughts:

a = getattr(c, 'foo')
b = getattr(c, 'foo')

a == b -> True
a is b -> False

The latter will result in True when the getattr for b comes from a cache.


From on June 08, 2010 14:20:05:
the generally accepted technique which i've seen is to add a local cached version of whatever attribute is being accessed.

ahh.... yes, of course: you'd need to delete that cached version if you changed the object.


From on June 16, 2010 20:05:52:
ok so wait... each object getattr'd has within it a cache of its own getattr-ness? :)


From on June 17, 2010 07:43:41:
Yep. Every instance would get a getattr_cache dict / object

c.getattr_cache['foo'] = getattr(c, 'foo')
The getattr(c, 'foo') would probably need a cmp method

"del c" would keep "a" and delete the cache too, and an additional "del a" would release all references.

I'm still puzzled about the handling of "a is b", which will miserably fail in pyjs if we take the getattr from the cache.

The "a == b" can also be solved by just adding a cmp method to the object that's returned form getattr()

The performance gain of using a cache is not big (I think), since is only helps where the getattr function is called, while the major performance loss is in calling the object returned by getattr.

So, I'm hesitating to go in the direction of caching getattr objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment