Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #3804 > unrolled thread

A question about Python Classes

Started bychad <cdalten@gmail.com>
First post2011-04-21 08:43 -0700
Last post2011-04-22 13:40 -0600
Articles 12 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  A question about Python Classes chad <cdalten@gmail.com> - 2011-04-21 08:43 -0700
    Re: A question about Python Classes Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-04-21 18:30 +0200
      Re: A question about Python Classes chad <cdalten@gmail.com> - 2011-04-21 09:46 -0700
    Re: A question about Python Classes "Pascal J. Bourguignon" <pjb@informatimago.com> - 2011-04-21 19:12 +0200
      Re: A question about Python Classes MRAB <python@mrabarnett.plus.com> - 2011-04-21 19:00 +0100
        Re: A question about Python Classes Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-04-22 01:53 +0000
      Re: A question about Python Classes Jean-Michel Pichavant <jeanmichel@sequans.com> - 2011-04-22 11:47 +0200
    Re: A question about Python Classes Terry Reedy <tjreedy@udel.edu> - 2011-04-21 13:39 -0400
    Re: A question about Python Classes Ethan Furman <ethan@stoneleaf.us> - 2011-04-21 11:34 -0700
      Re: A question about Python Classes "Kyle T. Jones" <onexpadREMOVE@EVOMERyahoodotyouknow.com> - 2011-04-22 08:49 -0500
        Re: A question about Python Classes Ethan Furman <ethan@stoneleaf.us> - 2011-04-22 12:38 -0700
        Re: A question about Python Classes Ian Kelly <ian.g.kelly@gmail.com> - 2011-04-22 13:40 -0600

#3804 — A question about Python Classes

Fromchad <cdalten@gmail.com>
Date2011-04-21 08:43 -0700
SubjectA question about Python Classes
Message-ID<2219ee53-e8aa-4ac4-839f-014c3d1b1914@a19g2000prj.googlegroups.com>
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

[toc] | [next] | [standalone]


#3809

FromJean-Michel Pichavant <jeanmichel@sequans.com>
Date2011-04-21 18:30 +0200
Message-ID<mailman.711.1303403421.9059.python-list@python.org>
In reply to#3804
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

[toc] | [prev] | [next] | [standalone]


#3811

Fromchad <cdalten@gmail.com>
Date2011-04-21 09:46 -0700
Message-ID<ebd6ad86-13ec-4968-b438-1fad42964a55@d26g2000prn.googlegroups.com>
In reply to#3809
On Apr 21, 9:30 am, Jean-Michel Pichavant <jeanmic...@sequans.com>
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

[toc] | [prev] | [next] | [standalone]


#3812

From"Pascal J. Bourguignon" <pjb@informatimago.com>
Date2011-04-21 19:12 +0200
Message-ID<87k4enil5g.fsf@kuiper.lan.informatimago.com>
In reply to#3804
chad <cdalten@gmail.com> 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 {}.

[toc] | [prev] | [next] | [standalone]


#3815

FromMRAB <python@mrabarnett.plus.com>
Date2011-04-21 19:00 +0100
Message-ID<mailman.715.1303408813.9059.python-list@python.org>
In reply to#3812
On 21/04/2011 18:12, Pascal J. Bourguignon wrote:
> chad<cdalten@gmail.com>  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'>

[toc] | [prev] | [next] | [standalone]


#3836

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-04-22 01:53 +0000
Message-ID<4db0dfab$0$29978$c3e8da3$5496439d@news.astraweb.com>
In reply to#3815
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

[toc] | [prev] | [next] | [standalone]


#3855

FromJean-Michel Pichavant <jeanmichel@sequans.com>
Date2011-04-22 11:47 +0200
Message-ID<mailman.739.1303465654.9059.python-list@python.org>
In reply to#3812
MRAB wrote:
> On 21/04/2011 18:12, Pascal J. Bourguignon wrote:
>> chad<cdalten@gmail.com>  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

[toc] | [prev] | [next] | [standalone]


#3814

FromTerry Reedy <tjreedy@udel.edu>
Date2011-04-21 13:39 -0400
Message-ID<mailman.714.1303407571.9059.python-list@python.org>
In reply to#3804
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

[toc] | [prev] | [next] | [standalone]


#3816

FromEthan Furman <ethan@stoneleaf.us>
Date2011-04-21 11:34 -0700
Message-ID<mailman.716.1303410257.9059.python-list@python.org>
In reply to#3804
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~

[toc] | [prev] | [next] | [standalone]


#3866

From"Kyle T. Jones" <onexpadREMOVE@EVOMERyahoodotyouknow.com>
Date2011-04-22 08:49 -0500
Message-ID<ios100$b0e$2@dont-email.me>
In reply to#3816
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.

[toc] | [prev] | [next] | [standalone]


#3886

FromEthan Furman <ethan@stoneleaf.us>
Date2011-04-22 12:38 -0700
Message-ID<mailman.760.1303500423.9059.python-list@python.org>
In reply to#3866
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<----------------------------------------------------------

[toc] | [prev] | [next] | [standalone]


#3888

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-04-22 13:40 -0600
Message-ID<mailman.762.1303501291.9059.python-list@python.org>
In reply to#3866
On Fri, Apr 22, 2011 at 7:49 AM, Kyle T. Jones
<onexpadREMOVE@evomeryahoodotyouknow.com> 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?

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web