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