A question about Python Classes

Discussion in 'Python' started by chad, Apr 21, 2011.

  1. chad

    chad Guest

    Let's say I have the following....

    class BaseHandler:
    def foo(self):
    print "Hello"

    class HomeHandler(BaseHandler):
    pass


    Then I do the following...

    test = HomeHandler()
    test.foo()

    How can HomeHandler call foo() when I never created an instance of
    BaseHandler?

    Chad
    chad, Apr 21, 2011
    #1
    1. Advertising

  2. chad wrote:
    > Let's say I have the following....
    >
    > class BaseHandler:
    > def foo(self):
    > print "Hello"
    >
    > class HomeHandler(BaseHandler):
    > pass
    >
    >
    > Then I do the following...
    >
    > test = HomeHandler()
    > test.foo()
    >
    > How can HomeHandler call foo() when I never created an instance of
    > BaseHandler?
    >
    > Chad
    >

    you did, test is an instance of BaseHandler.

    > isinstance(test, HomeHandler)

    < True

    > isinstance(test, BaseHandler)

    < True

    JM
    Jean-Michel Pichavant, Apr 21, 2011
    #2
    1. Advertising

  3. chad

    chad Guest

    On Apr 21, 9:30 am, Jean-Michel Pichavant <>
    wrote:
    > chad wrote:
    > > Let's say I have the following....

    >
    > > class BaseHandler:
    > >     def foo(self):
    > >         print "Hello"

    >
    > > class HomeHandler(BaseHandler):
    > >     pass

    >
    > > Then I do the following...

    >
    > > test = HomeHandler()
    > > test.foo()

    >
    > > How can HomeHandler call foo() when I never created an instance of
    > > BaseHandler?

    >
    > > Chad

    >
    > you did, test is an instance of BaseHandler.
    >
    >  > isinstance(test, HomeHandler)
    > < True
    >
    >  > isinstance(test, BaseHandler)
    > < True
    >


    So it just just creates an instance of every class that it inherits?

    Chad
    chad, Apr 21, 2011
    #3
  4. chad <> writes:

    > Let's say I have the following....
    >
    > class BaseHandler:
    > def foo(self):
    > print "Hello"
    >
    > class HomeHandler(BaseHandler):
    > pass
    >
    >
    > Then I do the following...
    >
    > test = HomeHandler()
    > test.foo()
    >
    > How can HomeHandler call foo() when I never created an instance of
    > BaseHandler?


    But you created one!

    test is an instance of HomeHandler, which is a subclass of BaseHandler,
    so test is also an instance of BaseHandler.

    A subclass represents a subset of the instances of its super class.

    --
    __Pascal Bourguignon__ http://www.informatimago.com/
    A bad day in () is better than a good day in {}.
    Pascal J. Bourguignon, Apr 21, 2011
    #4
  5. chad

    Terry Reedy Guest

    On 4/21/2011 11:43 AM, chad wrote:
    > Let's say I have the following....
    >
    > class BaseHandler:
    > def foo(self):
    > print "Hello"
    >
    > class HomeHandler(BaseHandler):
    > pass
    >
    >
    > Then I do the following...
    >
    > test = HomeHandler()
    > test.foo()
    >
    > How can HomeHandler call foo() when I never created an instance of
    > BaseHandler?


    When you ask for an attribute of an instance of a class, the attribute
    lookup first looks at the instance; if not there, then the class; if not
    there, then superclass(es); and so on back to class 'object'.

    >>> class C(): pass


    >>> c=C()
    >>> c.__hash__

    <method-wrapper '__hash__' of C object at 0x00FCB5D0>

    # how does this happen when C has no __hash__ method?

    >>> C.__hash__

    <slot wrapper '__hash__' of 'object' objects>

    # C inherits __hash__ and other special methods from 'object'

    >>> hash(c)

    1035101

    # uses the default, inherited method.

    Most syntactic operations and builtins are ultimately converted to a
    special method call, often inherited like this. In fact, c.x is
    converted to object.__getattribute__(c, 'x').

    >>> object.__getattribute__(c, '__hash__')

    <method-wrapper '__hash__' of C object at 0x00FCB5D0>

    You do need to understand inheritance. On the other hand, do not worry
    about behind-the-scenes implementation details like 'method_wrapper' and
    'slot_wrapper' classes, which may be CPython specific.

    --
    Terry Jan Reedy
    Terry Reedy, Apr 21, 2011
    #5
  6. chad

    MRAB Guest

    On 21/04/2011 18:12, Pascal J. Bourguignon wrote:
    > chad<> writes:
    >
    >> Let's say I have the following....
    >>
    >> class BaseHandler:
    >> def foo(self):
    >> print "Hello"
    >>
    >> class HomeHandler(BaseHandler):
    >> pass
    >>
    >>
    >> Then I do the following...
    >>
    >> test = HomeHandler()
    >> test.foo()
    >>
    >> How can HomeHandler call foo() when I never created an instance of
    >> BaseHandler?

    >
    > But you created one!
    >

    No, he didn't, he created an instance of HomeHandler.

    > test is an instance of HomeHandler, which is a subclass of BaseHandler,
    > so test is also an instance of BaseHandler.
    >

    test isn't really an instance of BaseHandler, it's an instance of
    HomeHandler, which is a subclass of BaseHandler.

    If you do this:

    class BaseHandler(object):
    def foo(self):
    print "Hello"

    class HomeHandler(BaseHandler):
    pass

    test = HomeHandler()

    then you'll find:

    >>> isinstance(test, BaseHandler)

    True

    but:

    >>> type(test)

    <class '__main__.HomeHandler'>
    MRAB, Apr 21, 2011
    #6
  7. chad

    Ethan Furman Guest

    chad wrote:
    > Let's say I have the following....
    >
    > class BaseHandler:
    > def foo(self):
    > print "Hello"
    >
    > class HomeHandler(BaseHandler):
    > pass
    >
    >
    > Then I do the following...
    >
    > test = HomeHandler()
    > test.foo()
    >
    > How can HomeHandler call foo() when I never created an instance of
    > BaseHandler?


    You don't need to create an instance of BaseHandler. You have the
    class, Python knows you have the class -- Python will look there if the
    subclasses lack an attribute.

    ~Ethan~
    Ethan Furman, Apr 21, 2011
    #7
  8. On Thu, 21 Apr 2011 19:00:08 +0100, MRAB wrote:

    >>> How can HomeHandler call foo() when I never created an instance of
    >>> BaseHandler?

    >>
    >> But you created one!
    >>

    > No, he didn't, he created an instance of HomeHandler.
    >
    >> test is an instance of HomeHandler, which is a subclass of BaseHandler,
    >> so test is also an instance of BaseHandler.
    >>

    > test isn't really an instance of BaseHandler, it's an instance of
    > HomeHandler, which is a subclass of BaseHandler.


    Which *also* makes it an instance of BaseHandler. You are a human being,
    which also makes you a mammal. It would be *wrong* to say that you're not
    a mammal, just because you're a human being.

    But to answer the Original Poster's question... you don't need a formal
    BaseHandler instance because that's how inheritance is designed to work.
    Each class knows its own parent classes, and when you call test.foo(),
    Python walks the chain of:

    instance
    instance's class
    each of the parent class(es) (if any)

    looking for a match for foo, and then calls it appropriately. This is
    called inheritance: HomeHandler inherits behaviour from BaseHandler.

    (The details are a little more complex than the sketch above, but broadly
    equivalent.)



    --
    Steven
    Steven D'Aprano, Apr 22, 2011
    #8
  9. MRAB wrote:
    > On 21/04/2011 18:12, Pascal J. Bourguignon wrote:
    >> chad<> writes:
    >>
    >>> Let's say I have the following....
    >>>
    >>> class BaseHandler:
    >>> def foo(self):
    >>> print "Hello"
    >>>
    >>> class HomeHandler(BaseHandler):
    >>> pass
    >>>
    >>>
    >>> Then I do the following...
    >>>
    >>> test = HomeHandler()
    >>> test.foo()
    >>>
    >>> How can HomeHandler call foo() when I never created an instance of
    >>> BaseHandler?

    >>
    >> But you created one!
    >>

    > No, he didn't, he created an instance of HomeHandler.

    I think this is really wrong within the OP question context. This is a
    key concept about OOP and inheritance, any object of class HomeHandler
    is an object of class BaseHandler and also an object of any other base
    class.

    However it is true that for convenience, there are some language abuses
    around this terms that we're all using, for instance:
    - class refers to the lowest class of the object (like the python
    __class__ attribute)
    - "instance of" means sometimes "created using the constructor of"
    when stating for example that you cannot create an instance of a
    virtual class. From a formal OO POV, anyone can create an instance of a
    virtual class, you just need to create an instance of one of its
    subclass. What you cannot, is create a instance of a virtual class using
    the constructor of that virtual class.

    Also note that
    isinstance(test, BaseHandler)
    returns True. And this is no Python trick to trigger some magic, this is
    what OO is about.


    JM
    Jean-Michel Pichavant, Apr 22, 2011
    #9
  10. Ethan Furman wrote:
    > chad wrote:
    >> Let's say I have the following....
    >>
    >> class BaseHandler:
    >> def foo(self):
    >> print "Hello"
    >>
    >> class HomeHandler(BaseHandler):
    >> pass
    >>
    >>
    >> Then I do the following...
    >>
    >> test = HomeHandler()
    >> test.foo()
    >>
    >> How can HomeHandler call foo() when I never created an instance of
    >> BaseHandler?

    >
    > You don't need to create an instance of BaseHandler. You have the
    > class, Python knows you have the class -- Python will look there if the
    > subclasses lack an attribute.
    >
    > ~Ethan~
    >


    Really? That's not at all how I thought it worked in Python
    (post-instantiation referencing of class and superclass code...)

    Cheers.
    Kyle T. Jones, Apr 22, 2011
    #10
  11. chad

    Ethan Furman Guest

    Kyle T. Jones wrote:
    > Ethan Furman wrote:
    >> chad wrote:
    >>> Let's say I have the following....
    >>>
    >>> class BaseHandler:
    >>> def foo(self):
    >>> print "Hello"
    >>>
    >>> class HomeHandler(BaseHandler):
    >>> pass
    >>>
    >>>
    >>> Then I do the following...
    >>>
    >>> test = HomeHandler()
    >>> test.foo()
    >>>
    >>> How can HomeHandler call foo() when I never created an instance of
    >>> BaseHandler?

    >>
    >> You don't need to create an instance of BaseHandler. You have the
    >> class, Python knows you have the class -- Python will look there if the
    >> subclasses lack an attribute.
    >>
    >> ~Ethan~
    >>

    >
    > Really? That's not at all how I thought it worked in Python
    > (post-instantiation referencing of class and superclass code...)


    I'm not sure exactly what you're asking/stating, but does this help?

    8<---Py 3.2 code------------------------------------------
    class BaseClass():
    def bFoo(self):
    print("Base foo here!")

    class NormalClass(BaseClass):
    def nFoo(self):
    print("Normal foo here.")

    class EnhancedClass(NormalClass):
    def eFoo(self):
    print("Enhanced foo comin' at ya!")

    class EnrichedClass(EnhancedClass):
    def rFoo(self):
    print("Am I glowing yet?")

    test = EnrichedClass()
    test.bFoo()
    test.nFoo()
    test.eFoo()
    test.rFoo()

    def newFoo(self):
    print("Ha! You've been replaced!")

    BaseClass.bFoo = newFoo

    test.bFoo()
    8<----------------------------------------------------------
    Ethan Furman, Apr 22, 2011
    #11
  12. chad

    Ian Kelly Guest

    On Fri, Apr 22, 2011 at 7:49 AM, Kyle T. Jones
    <> wrote:
    >> You don't need to create an instance of BaseHandler.  You have the
    >> class, Python knows you have the class -- Python will look there if the
    >> subclasses lack an attribute.
    >>
    >> ~Ethan~
    >>

    >
    > Really?  That's not at all how I thought it worked in Python
    > (post-instantiation referencing of class and superclass code...)


    Yes, it looks up the attribute in the superclass tree at the time that
    it's referenced, not at the time it's instantiated or at the time the
    class is created. So:

    >>> class Base(object):

    .... x = 5
    ....
    >>> class Test(Base):

    .... pass
    ....
    >>> t = Test()
    >>> t.x

    5
    >>> Test.x = 42
    >>> t.x

    42
    >>> Base.x = 7
    >>> del Test.x
    >>> t.x

    7

    Or were you talking about something else?
    Ian Kelly, Apr 22, 2011
    #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. David

    Classes within classes

    David, Jul 21, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    4,921
    David
    Jul 22, 2005
  2. lonelyplanet999
    Replies:
    1
    Views:
    2,188
    VisionSet
    Nov 13, 2003
  3. Carlo v. Dango
    Replies:
    14
    Views:
    996
    Alex Martelli
    Oct 19, 2003
  4. August0866
    Replies:
    1
    Views:
    102
    Sebastian Hungerecker
    Mar 17, 2008
  5. vasudevram
    Replies:
    6
    Views:
    907
    vasudevram
    Apr 24, 2013
Loading...

Share This Page