super - python: cooperative supercall of __getattr__ -


i'm working somethign similar code:

class baseclass(object):     def __getattr__(self, attr):         return lambda:'1'  class subclass(baseclass):     def foo(self):         suffix = '2'         return super(subclass, self).foo() + suffix  class subclass2(subclass):     def foo(self):         suffix = '3'         return super(subclass2, self).foo() + suffix  o = subclass2() print o.foo() 

i'd expect see output of '123', instead error attributeerror: 'super' object has no attribute 'foo'. python isn't attempting use base class's __getattr__.

without modifying base class, , keeping 2 super calls similar, i'm not able output want. there cooperative supercall pattern work me here?

i understand super() overrides getattr in way needs do, i'm asking if there's reasonable workaround allows subclass's __getattr__ called when appropriate.

ah, great question!

in short, what's going on here cpython internals take shortcuts when doing attribute lookups, , kind of surprising behaviour 1 of consequences (another 1 being improved performance).

to understand what's happening in situation, need venture definition of super: http://hg.python.org/cpython/file/c24941251473/objects/typeobject.c#l6689

notice doesn't define tp_getattr (aka __getattr__), define tp_getattro (aka __getattribute__):

pytypeobject pysuper_type = {     pyvarobject_head_init(&pytype_type, 0)     "super",                                    /* tp_name */     ...     0,                                          /* tp_getattr */     ...     super_getattro,                             /* tp_getattro */     ... }; 

(recall __getattribute__ called every time attribute requested, opposed __getattr__, called if attribute doesn't exist on object (roughly: if attribute isn't in object's __dict__)).

next, looking definition of super_getattro (aka super.__getattribute__), can see implementation approximately:

class super(object):     def __init__(self, obj_type, obj):         self.obj_type = obj_type         self.obj = obj      def __getattribute__(self, attr):         = self.obj_type.__mro__.find(self.obj_type)         += 1         while < len(obj_type.__mro__):             cur_type = self.obj_type.__mro__[i]             cur_dict = cur_type.__dict___             res = cur_dict.get(attr)             if res not none:                 return res             += 1         return object.__getattribute__(self, attr) 

which makes obvious why super doesn't play __getattr__super checking attributes in parent class' __dict__!

fun aside: seems pypy (as of 2.1.0) behaves same way:

$ pypy super.py  traceback (most recent call last):   file "app_main.py", line 72, in run_toplevel   file "super.py", line 16, in <module>     print o.foo()   file "super.py", line 13, in foo     return super(subclass2, self).foo() + suffix   file "super.py", line 8, in foo     return super(subclass, self).foo() + suffix attributeerror: 'super' object has no attribute 'foo' 

Comments

Popular posts from this blog

java - Run a .jar on Heroku -

java - Jtable duplicate Rows -

validation - How to pass paramaters like unix into windows batch file -