conditional __init__

K

King

class A(object):
def __init__(self):
pass
def printme(self):
print "I am A"

class B(object):
def __init__(self):
pass
def printme(self):
print "I am B"

class K(A, B):
def __init__(self, value=0):
if value == 0:
A.__init__(self)
print "__init__ A"
elif value == 1:
B.__init__(self)
print "__init__ B"
self.printme()

o = K(value=1)

Output
In above code "B" is correctly getting initialized as per condition.
How ever method "printme" is printing "I am A".
Instead it has to print "I am B" because "B" is the one that has been
initialized. What's wrong here?

Is there a better/another way to do conditional initialization as
needed above?

Cheers

Prashant
Python 2.6.2
Win XP 32
 
C

Chris Rebert

class A(object):
   def __init__(self):
       pass
   def printme(self):
       print "I am A"

class B(object):
   def __init__(self):
       pass
   def printme(self):
       print "I am B"

class K(A, B):
   def __init__(self, value=0):
       if value == 0:
           A.__init__(self)
           print "__init__ A"
       elif value == 1:
           B.__init__(self)
           print "__init__ B"
       self.printme()

o = K(value=1)

Output

In above code "B" is correctly getting initialized as per condition.
How ever method "printme" is printing "I am A".
Instead it has to print "I am B" because "B" is the one that has been
initialized. What's wrong here?

Is there a better/another way to do conditional initialization as
needed above?

Which initializers are called *has no effect* on what order base
classes are consulted in when looking up methods. To change the lookup
order, you need to change the order of the base classes in the class
statement.

Your problem could be fixed by:

1. Changing the code so the initializers do have an effect through
what they initialize instance variables to;
class A(object):
def __init__(self):
self.name = "A"
def printme(self):
print "I am", self.name

class B(object):
def __init__(self):
self.name = "B"
def printme(self):
print "I am", self.name

2. Use a factory function to return an instance of the proper class:

class K1(A, B):
pass

class K2(B, A):
pass

def newK(value):
if value == 0:
return K1()
elif value == 1:
return K2()

Cheers,
Chris
 
O

OKB (not okblacke)

King said:
class A(object):
def __init__(self):
pass
def printme(self):
print "I am A"

class B(object):
def __init__(self):
pass
def printme(self):
print "I am B"

class K(A, B):
def __init__(self, value=0):
if value == 0:
A.__init__(self)
print "__init__ A"
elif value == 1:
B.__init__(self)
print "__init__ B"
self.printme()

o = K(value=1)

Output

In above code "B" is correctly getting initialized as per condition.
How ever method "printme" is printing "I am A".
Instead it has to print "I am B" because "B" is the one that has been
initialized. What's wrong here?

It prints "I am A" because K inherits from A before B. Your
__init__ methods don't do anything, so it doesn't matter which one you
call. You seem to be thinking that running __init__ magically
determines the class of the object, but it doesn't; it's just code that
runs when the object is first created. When you do self.printme(), it
decides to use A.printme because you did "class K(A, B)". If you do
class K(B, A)" it will use B.printme.

I imagine it's possible to do fiendish things and try to choose the
superclass inheritance order at runtime, but you should be wary of this.
In your example, why don't you just have K override printme and dispatch
to A or B depending on "value"?

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
C

Carl Banks

class A(object):
    def __init__(self):
        pass
    def printme(self):
        print "I am A"

class B(object):
    def __init__(self):
        pass
    def printme(self):
        print "I am B"

class K(A, B):
    def __init__(self, value=0):
        if value == 0:
            A.__init__(self)
            print "__init__ A"
        elif value == 1:
            B.__init__(self)
            print "__init__ B"
        self.printme()

o = K(value=1)

Output


In above code "B" is correctly getting initialized as per condition.
How ever method "printme" is printing "I am A".
Instead it has to print "I am B" because "B" is the one that has been
initialized. What's wrong here?

What's wrong is that you have a fundamental misunderstanding of what's
happening. You can't just shut off a subclass by refusing to
initialize it--just doesn't work that way. All subclasses will
continue to be active whether you call __init__ on them or not.
Therefore when you call self.printme() it searches the base classes in
order, and the first one it finds is A, so it always calls A's
printme.

It seems to me that you haven't learned enough about how inheritance
works in Python to use multiple inheritance yet, so I would suggest
just sticking to single inheritance for now, and study up.

Is there a better/another way to do conditional initialization as
needed above?

The fact that you feel the need to do this suggests that you want a
composition relationship, not an inheritance one. What you appear to
be doing is defining a sort of "plugin", you have an object that can
behave one way (A) or another (B), but which one isn't known till run
time. In that case the A or B object should be made an attribute of
the K object:

class A(object):
def printme(self):
print "I am A"

class B(object):
def printme(self):
print "I am B"

class K(object):
def __init__(self, value=0):
if value == 0:
self.plugin = A()
print "__init__ A"
elif value == 1:
self.plugin = B()
print "__init__ B"
self.plugin.printme()


Without seeing more of your code I strongly suspect that this change
better reflects what you're trying to do.


Carl Banks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top