trouble understanding inheritance...

Discussion in 'Python' started by KraftDiner, Aug 16, 2006.

  1. KraftDiner

    KraftDiner Guest

    This is not working the way I think it should....
    it would appear that fromfile and getName are calling the baseClass
    methods which are
    simple passes.... What have I done wrong?

    class baseClass:
    def __init__(self, type):
    if type == 'A':
    self = typeA()
    else:
    self = typeB()
    def fromfile(self):
    pass
    def getName(self):
    pass

    class typeA(baseClass):
    def __init__(self):
    self.name='A'
    print 'typeA init'
    def fromfile(self):
    print 'typeA fromfile'
    def getName(self):
    print self.name

    class typeB(baseClass):
    def __init__(self):
    self.name='B'
    print 'typeB init'
    def fromfile(self):
    print 'typeB fromfile'
    def getName(self):
    print self.name

    a = baseClass('A')
    a.fromfile()
    a.getName()

    b = baseClass('B')
    b.fromfile()
    b.getName()

    log:
    typeA init
    typeB init
     
    KraftDiner, Aug 16, 2006
    #1
    1. Advertising

  2. KraftDiner wrote:

    > This is not working the way I think it should....
    > it would appear that fromfile and getName are calling the baseClass
    > methods which are
    > simple passes.... What have I done wrong?
    >
    > class baseClass:
    > def __init__(self, type):
    > if type == 'A':
    > self = typeA()
    > else:
    > self = typeB()


    __init__ is not a constructor, and assigning to self doesn't change the
    type of the constructed object.

    looks like you need to get a better tutorial.

    </F>
     
    Fredrik Lundh, Aug 16, 2006
    #2
    1. Advertising

  3. KraftDiner

    KraftDiner Guest

    Fredrik Lundh wrote:
    > KraftDiner wrote:
    >
    > > This is not working the way I think it should....
    > > it would appear that fromfile and getName are calling the baseClass
    > > methods which are
    > > simple passes.... What have I done wrong?
    > >
    > > class baseClass:
    > > def __init__(self, type):
    > > if type == 'A':
    > > self = typeA()
    > > else:
    > > self = typeB()

    >
    > __init__ is not a constructor, and assigning to self doesn't change the
    > type of the constructed object.
    >
    > looks like you need to get a better tutorial.
    >
    > </F>


    Well how does one select which class baseClass really is when you
    contruct the object?
    What am I missing?

    a = typeA()
    b = typeB()
    c = baseClass(a)
     
    KraftDiner, Aug 16, 2006
    #3
  4. KraftDiner

    Simon Forman Guest

    KraftDiner wrote:
    > Fredrik Lundh wrote:
    > > KraftDiner wrote:
    > >
    > > > This is not working the way I think it should....
    > > > it would appear that fromfile and getName are calling the baseClass
    > > > methods which are
    > > > simple passes.... What have I done wrong?
    > > >
    > > > class baseClass:
    > > > def __init__(self, type):
    > > > if type == 'A':
    > > > self = typeA()
    > > > else:
    > > > self = typeB()

    > >
    > > __init__ is not a constructor, and assigning to self doesn't change the
    > > type of the constructed object.
    > >
    > > looks like you need to get a better tutorial.
    > >
    > > </F>

    >
    > Well how does one select which class baseClass really is when you
    > contruct the object?
    > What am I missing?
    >
    > a = typeA()
    > b = typeB()
    > c = baseClass(a)


    a = typeA()
    b = typeB()

    You're done. Stop there.

    You can't "select which class baseClass really is"-- it really is
    baseClass. You "select" which class your object is by choosing which
    class to use to construct the object.

    HTH,
    ~Simon
     
    Simon Forman, Aug 16, 2006
    #4
  5. KraftDiner

    KraftDiner Guest

    Simon Forman wrote:
    > KraftDiner wrote:
    > > Fredrik Lundh wrote:
    > > > KraftDiner wrote:
    > > >
    > > > > This is not working the way I think it should....
    > > > > it would appear that fromfile and getName are calling the baseClass
    > > > > methods which are
    > > > > simple passes.... What have I done wrong?
    > > > >
    > > > > class baseClass:
    > > > > def __init__(self, type):
    > > > > if type == 'A':
    > > > > self = typeA()
    > > > > else:
    > > > > self = typeB()
    > > >
    > > > __init__ is not a constructor, and assigning to self doesn't change the
    > > > type of the constructed object.
    > > >
    > > > looks like you need to get a better tutorial.
    > > >
    > > > </F>

    > >
    > > Well how does one select which class baseClass really is when you
    > > contruct the object?
    > > What am I missing?
    > >
    > > a = typeA()
    > > b = typeB()
    > > c = baseClass(a)

    >
    > a = typeA()
    > b = typeB()
    >
    > You're done. Stop there.
    >

    I can see that this might work...
    c = [a, b]
    for c in [a,b]:
    c.getName()

    but when does baseClass ever get used?
    Why did i even have to define it?



    > You can't "select which class baseClass really is"-- it really is
    > baseClass. You "select" which class your object is by choosing which
    > class to use to construct the object.
    >
    > HTH,
    > ~Simon
     
    KraftDiner, Aug 16, 2006
    #5
  6. On 16 Aug 2006 12:53:12 -0700, KraftDiner <> wrote:
    > I can see that this might work...
    > c = [a, b]
    > for c in [a,b]:
    > c.getName()
    >
    > but when does baseClass ever get used?
    > Why did i even have to define it?


    Well, quite.

    --
    Cheers,
    Simon B,
    ,
    http://www.brunningonline.net/simon/blog/
     
    Simon Brunning, Aug 16, 2006
    #6
  7. KraftDiner

    KraftDiner Guest

    Simon Brunning wrote:
    > On 16 Aug 2006 12:53:12 -0700, KraftDiner <> wrote:
    > > I can see that this might work...
    > > c = [a, b]
    > > for c in [a,b]:
    > > c.getName()
    > >
    > > but when does baseClass ever get used?
    > > Why did i even have to define it?

    >
    > Well, quite.
    >

    I agree... welll... quite... :)


    > --
    > Cheers,
    > Simon B,
    > ,
    > http://www.brunningonline.net/simon/blog/
     
    KraftDiner, Aug 16, 2006
    #7
  8. On Wed, 16 Aug 2006 12:53:12 -0700, KraftDiner wrote:

    >> > Well how does one select which class baseClass really is when you
    >> > contruct the object?
    >> > What am I missing?
    >> >
    >> > a = typeA()
    >> > b = typeB()
    >> > c = baseClass(a)

    >>
    >> a = typeA()
    >> b = typeB()
    >>
    >> You're done. Stop there.
    >>

    > I can see that this might work...
    > c = [a, b]
    > for c in [a,b]:
    > c.getName()
    >
    > but when does baseClass ever get used?
    > Why did i even have to define it?


    So that you don't duplicate code. That's it.

    Here is a basic example. I have a class Foo with a method foo() that
    returns "foo", and a second class Foos which is *almost* the same except
    method foo() takes an argument and returns that number of foos.

    class BaseClass():
    def foo(self):
    return "foo"

    class Foo(BaseClass):
    def foo(self):
    return self.__class__.foo() # call the parent class method

    class Foos(BaseClass):
    def foo(self, n):
    return self.__class__.foo() * n


    Obviously in this case, there is no real need for BaseClass -- Foos could
    inherit from Foo. But in more complex cases, you might need something like
    this.

    Hope this helps.


    --
    Steven D'Aprano
     
    Steven D'Aprano, Aug 17, 2006
    #8
  9. KraftDiner

    Jason Guest

    KraftDiner wrote:
    > c = [a, b]
    > for c in [a,b]:
    > c.getName()
    >
    > but when does baseClass ever get used?
    > Why did i even have to define it?
    >


    One reason for using base classes are for logical reasons. Oranges and
    Apples are different, but they are both fruits. Python has both
    unicode strings and 8-bit ASCII strings. Both are strings and share a
    common base class: the 'basestring' class.

    A second reason is for code sharing. Let's say Python's string class
    does everything you want already... except for one little thing. You
    want the split method to return a list with some extra information.
    Why re-invent the wheel trying to implement the other string methods
    when you can reuse everything that's already been done?

    >>> class MyString(str):

    .... def split(self):
    .... "Perform some extra work this version of split"
    .... wordList = str.split(self) # Call the original method
    .... return ['Extra'] + wordList + ['Information'] # Do additional
    work!
    ....
    >>>


    In Python, we often rely on duck typing. "If it looks like a duck,
    quacks like a duck, it's a duck." If we can treat it like a string, we
    can consider it a string. If we can't treat it like a string, Python
    will let us know by raising an exception. We can catch this exception
    and try something different, or let the exception stop the program and
    let the user know something went wrong.

    Duck typing allows us to re-use code very efficiently. I'll
    demonstrate it with a function and the class defined above.

    >>> def GetWords(stringValue):

    .... "Print the list of words in a string"
    .... print 'Words are: %s' % stringValue.split()
    ....
    >>> stringValue = str('Hello, world!')
    >>> unicodeValue = unicode('These are different strings')
    >>> myStringValue = MyString('good, hopefully useful')
    >>>
    >>> GetWords(stringValue)

    Words are: ['Hello,', 'world!']
    >>> GetWords(unicodeValue)

    Words are: [u'These', u'are', u'different', u'strings']
    >>> GetWords(myStringValue)

    Words are: ['Extra', 'good,', 'hopefully', 'useful', 'Information']
    >>>


    As shown above, the GetWords() function works fine with my new string
    class. Any methods that I didn't redefine keep their old behavior.
    For example, I didn't define the upper() method in MyString, but I can
    still use it:

    >>> stringValue.upper()

    'HELLO, WORLD!'
    >>> myStringValue.upper()

    'GOOD, HOPEFULLY USEFUL'
    >>>


    While we rely on duck typing in Python, we occassionally want special
    behavior for certain types of data. Currently, you can pass anything
    into the GetWords() function that has a method named 'split'. It does
    not have to be a string:

    >>> class NotAString(object):

    .... def split(self):
    .... return 'I am not a string!'
    ....
    >>> otherDataValue = NotAString()
    >>> GetWords(otherDataValue)

    Words are: I am not a string!
    >>>


    Sometimes, we want some specialized behavior. Lists, tuples, and
    strings all act like sequences (meaning, you can get their length and
    use them in for-loops). Often, though, you'll want to treat strings
    differently. You can check the type directly, or you can check by
    using the isinstance() built-in function. isinstance() checks to see
    if a variable is an instance of a class or any of its subclasses.

    Remember the first reason given, of using a base class to logically
    organize other classes? This is it in practice. I'll demonstrate
    below:

    >>> def CheckOnlyBuiltinStrings(stringValue):

    .... "Tells us whether or not stringValue is a str or unicode string."
    .... if type(stringValue) is str or type(stringValue) is unicode:
    .... print 'A built-in string type: %s' % stringValue
    .... else:
    .... print 'Not a built-in string type: %s' % stringValue
    ....
    >>> def CheckAllStrings(stringValue):

    .... "Tells us whether or not stringValue is a string."
    .... # The basestring class is a superclass for all string classes.
    .... if isinstance(stringValue, basestring):
    .... print 'Is a string: %s' % stringValue
    .... else:
    .... print 'Not a string: %s' % stringValue
    ....
    >>> CheckOnlyBuiltinStrings(stringValue)

    A built-in string type: Hello, world!
    >>> CheckOnlyBuiltinStrings(unicodeValue)

    A built-in string type: These are different strings
    >>> CheckOnlyBuiltinStrings(myStringValue)

    Not a built-in string type: good, hopefully useful
    >>>
    >>> CheckAllStrings(stringValue)

    Is a string: Hello, world!
    >>> CheckAllStrings(unicodeValue)

    Is a string: These are different strings
    >>> CheckAllStrings(myStringValue)

    Is a string: good, hopefully useful
    >>> CheckAllStrings(42)

    Not a string: 42
    >>>


    How do you know when you should use type() checks, when you should use
    isinstance(), and when you should just try to use the data? That
    depends, and there have been many lively debates on this subject in the
    newsgroup. I recommend that you should only use as much type checking
    as needed, and the less is better.

    A bit long, but I hope this helps you out.

    --Jason
     
    Jason, Aug 17, 2006
    #9
  10. KraftDiner

    Ant Guest

    Try running the following example - it should help clear up what is
    going on:

    class Base:
    def __init__(self):
    print "Initializing base"
    def shouldBeImplemented(self):
    raise NotImplementedError
    def hasDefaultImplementation(self):
    print "Wey Hey!"

    class A(Base):
    def shouldBeImplemented(self):
    print "Has been implemented!"

    class B(Base):
    def __init__(self):
    Base.__init__(self)
    print 'Initializing B'

    class C(Base):
    def __init__(self):
    print "Initializing C"
    def hasDefaultImplementation(self):
    print "Boo Hoo!"

    base = Base()
    print "\n------- A --------"
    a = A()
    a.shouldBeImplemented()
    print "\n------- B --------"
    b = B()
    b.hasDefaultImplementation()
    print "\n------- C --------"
    c = C()
    c.hasDefaultImplementation()
    c.shouldBeImplemented()
     
    Ant, Aug 17, 2006
    #10
  11. KraftDiner

    enigmadude Guest

    If what you're trying to do is have more control over the type of
    object that is instantiated, then you could use a function that decides
    what class to use based upon the arguments supplied to the function,
    where it then instantiates an object from the chosen class, then
    returns the object. The __init__ method is just for initialization when
    an object is created, it's not a constructor and you could even leave
    it out and still be able to create objects (although that's less useful
    in most cases). Changing an object's type after it's already been
    created is more advanced. It's useful, but I don't think that's what
    you're trying to do. I believe you're just trying to allow the program
    to have more control over what type of object to create. Try doing a
    Google search for "creational design patterns", "factory function", and
    "factory method". Here's a simple example of what I'm talking about:

    def factory(chosen):
    if chosen == 'a':
    obj = typeA()
    elif chosen == 'b':
    obj = typeB()

    return obj


    KraftDiner wrote:
    > This is not working the way I think it should....
    > it would appear that fromfile and getName are calling the baseClass
    > methods which are
    > simple passes.... What have I done wrong?
    >
    > class baseClass:
    > def __init__(self, type):
    > if type == 'A':
    > self = typeA()
    > else:
    > self = typeB()
    > def fromfile(self):
    > pass
    > def getName(self):
    > pass
    >
    > class typeA(baseClass):
    > def __init__(self):
    > self.name='A'
    > print 'typeA init'
    > def fromfile(self):
    > print 'typeA fromfile'
    > def getName(self):
    > print self.name
    >
    > class typeB(baseClass):
    > def __init__(self):
    > self.name='B'
    > print 'typeB init'
    > def fromfile(self):
    > print 'typeB fromfile'
    > def getName(self):
    > print self.name
    >
    > a = baseClass('A')
    > a.fromfile()
    > a.getName()
    >
    > b = baseClass('B')
    > b.fromfile()
    > b.getName()
    >
    > log:
    > typeA init
    > typeB init
     
    enigmadude, Aug 17, 2006
    #11
  12. Steven D'Aprano a écrit :
    (snip)
    > class BaseClass():
    > def foo(self):
    > return "foo"
    >
    > class Foo(BaseClass):
    > def foo(self):
    > return self.__class__.foo() # call the parent class method


    Err... May I suggest that you re-read the Fine Manual ?
     
    Bruno Desthuilliers, Aug 27, 2006
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ric Pullen

    Trouble understanding StateServer!!

    Ric Pullen, Jul 23, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    376
    Ric Pullen
    Jul 23, 2004
  2. Rob
    Replies:
    1
    Views:
    443
    Victor Bazarov
    Mar 7, 2004
  3. Jakle

    trouble understanding None

    Jakle, Nov 12, 2003, in forum: Python
    Replies:
    9
    Views:
    347
    Alex Martelli
    Nov 13, 2003
  4. slyraymond
    Replies:
    5
    Views:
    279
    Mark Lutz
    Apr 26, 2004
  5. John Salerno

    trouble understanding super()

    John Salerno, Jul 31, 2006, in forum: Python
    Replies:
    4
    Views:
    304
    John Salerno
    Jul 31, 2006
Loading...

Share This Page