Inheritance and forward references (prototypes)

Lorenzo Di Gregorio lorenzo.digregorio at gmail.com
Sun Jun 21 07:55:45 EDT 2009


On 21 Jun., 01:54, Dave Angel <da... at ieee.org> wrote:
> LorenzoDiGregoriowrote:
> > On Jun 20, 8:43 pm, Dave Angel <da... at ieee.org> wrote:
>
> >>LorenzoDiGregoriowrote:
>
> >>> 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- Zitierten Text ausblenden -
>
> - Zitierten Text anzeigen -

I had also thought of using "None" (or whatever else) as a marker but
I was curious to find out whether there are better ways to supply an
object with standard values as a default argument.
In this sense, I was looking for problems ;-)

Of course the observation that "def" is an instruction and no
declaration changes the situation: I would not have a new object being
constructed for every instantiation with no optional argument, because
__init__ gets executed on the instantiation but test=A() gets executed
on reading 'def'.

At this point I think there is no other way than using a marker as
suggested above multiple times, if I want to supply a new object with
default values for non-passed arguments.

Anybody with a better idea?



More information about the Python-list mailing list