Inheritance and forward references (prototypes)

Dave Angel davea at ieee.org
Sun Jun 21 01:54:46 CEST 2009


Lorenzo Di Gregorio wrote:
> On Jun 20, 8:43 pm, Dave Angel <da... at ieee.org> wrote:
>   
>> Lorenzo Di Gregorio wrote:
>>     
>>> Hi,
>>>       
>>> I'm wondering what would be the preferred way to solve the following
>>> forward reference problem:
>>>       
>>> ---------------------------------------
>>> class BaseA(object):
>>>     def __init__(self):
>>>         return
>>>       
>>> class DebugA(BaseA):
>>>     def __init__(self):
>>>         return
>>>       
>>> # here I would have a prototype of class A which is the same as class
>>> BaseA
>>>       
>>> class B(object):
>>>     def __init__(self):
>>>         self.obj =()
>>>         return
>>>       
>>> if __name__ ="__main__":
>>> #    class A(BaseA): # Uncomment this for using BaseA objects
>>> #       pass
>>>     class A(DebugA): # Uncomment this for using DebugA objects
>>>         pass
>>> ---------------------------------------
>>>       
>>> I can figure out some ways to fix this but none seems satisfying.
>>> Either they are too specific or too cumbersome.
>>> A runtime redefinition of class A does not seem to work either.
>>> What would be the most "pythonesque" solution other than sorting out
>>> the class order?
>>>       
>>> Best Regards,
>>> Lorenzo
>>>       
>> You haven't shown us any problem.  class B works fine with a forward
>> reference to A.  Now if you were trying to subclass A before defining
>> it, that'd be a problem.  Or if you were trying to make an instance of B
>> before defining A.
>>
>> Better put some code together with enough meat to actually show a
>> symptom.  And tell us what sys.version says.  I'm testing with   2.6.2
>> (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)], running
>> on Win XP.- Hide quoted text -
>>
>> - Show quoted text -
>>     
>
> Thank you for your help: I'm working on a rather large source, but I
> think I have isolated the problem now.
> This listing generates an error:
>
> -----------------------------------------------
> class BaseA(object):
>     def __init__(self):
>         return
>
> class DebugA(BaseA):
>     def __init__(self):
>         return
>
> class B(object):
>     def __init__(self,test=A()):
>         self.obj =()
>         return
>
> if __name__ ="__main__":
> #    class A(BaseA): # Uncomment this for using BaseA objects
> #        pass
>      class A(DebugA): # Uncomment this for using DebugA objects
>          pass
> -----------------------------------------------
>
> The error happens because Python apparently evaluates the named
> arguments before running the script.
> I think I have read something about this some (long) time ago but I
> can't find it anymore.
>
> Suggestions?
>
> BTW, my Python version is 2.6.1 (with latest PyDev).
>
> Thx!
> Lorenzo
>
>   
This error is caused because a default argument uses class A.  Default 
arguments of class methods are evaluated during the definition of the 
class, and not later when the class is instantiated.  Thus the problem.

To work around that specific problem, you may want to use the following:

class B(object):
    def __init__(self,test=None):
        if test==None:
            test = A()
        self.obj =()
        return


This is actually different than what you had, since what you had would 
have used the same A() object for all instances of B that didn't supply 
their own test() parameter.  Maybe that's what you wanted, and maybe 
not, but default arguments set to mutable values are frequently a bug.

But I'm wondering if you're just looking for problems.  Why not put the 
commented switch early in the file, and test for it wherever you need to 
use it?

import  x, y, z
_debug = False
#_debug = True


then as soon as  BaseA and DebugA are defined, do the following:

if _debug:
    class A(DebugA):
        pass
else:
    class A(BaseA)
        pass





More information about the Python-list mailing list