NEWBIE: Sub-classes revisited

Gabriel Genellina gagenellina at softlab.com.ar
Fri Jan 2 19:49:03 EST 2004


At 31/12/2003 15:47, you wrote:

># IN MOD_1.PY
>
>class B:
>     def __init__ (self):
>         self.B_init_var = 1
>     def B_meth(self):
>         self.B_meth_var = 2
>
># IN MOD_2.PY
>
>import mod_1
>
>class A(mod_1.B):              # B needs to be qualified
>     def __init__(self):
>         mod_1.B.__init__(self) # Needs to be qualified
>         self.B_meth()          # But B's method doesn't
>         print self.B_init_var  # Just to be sure
>         print self.B_meth_var  # Ditto

Apart from trial-and-error and self-discoving things, which is really good, 
you should read the Python Tutorial which is very good too. If you did 
already, do it again, specially section 9 (Classes).

>Is the following true?
>
>1. When A is instantiated, B's name space is exposed
>    to A.

No. Python uses dynamic binding. If you come from a statically-binded 
language like Java or C++ this may be confusing. In Python, the attributes 
and methods are searched *looking*inside*the*instance*, not by knowledge of 
some prior declarations of type.
At the beginning of A.__init__ the 'self' parameter has been constructed, 
and you can use its attributes and methods (as far as nothing depends of 
__init__). By example, you can use: self.B_meth()


>2. B is not instantiated when A is,
>    therefore B's init is not run.

No. The object is already constructed; __init__ is an initializer, not a 
constructor. See above.

>3. If A can't find B_meth in it's own namespace,
>    it looks in B's namespace.

Yes. And if not found there, in its parent and so on. See section 9.5.1 in 
the Python tutorial.

>4. If one attempts to run B's init in A's init,
>    using self.__init__(), one is in for a long wait...:)

Yes...

>5. B's init in A's init must be qualified to prevent #4

Yes, and to specify *which* init you want to call, in case of multiple 
inheritance.

>6. The proper terminology is:
>    'A inherits B's methods and attributes'

Yes. Maybe a purist would object something but it's ok...

>7. An init in B is of limited usefulness.

Why? B.__init__ should do whatever is needed to properly initialize class 
B. Usually you inherit to specialize behaviour. In BaseHTTPServer.py you 
have class HTTPServer which inherits from TCPServer which inherits from 
BaseServer; each one has its own responsabilities; altough you could have 
written all that stuff in just one class, that would be difficult to reuse 
or modify.

>8. If all one needs is to 'declare and inialize'
>    variables common to a number of classes, one
>    really doesn't need a base class,
>    just a module containing the 'constants'.
>    But if there are methods which are semi-common
>    to all sub-classes, and can be overidden or
>    extended to do the job, then it makes sense to
>    use inheritance.

Mmm, no. In an OO environment, classes are used to build a *model* of 
something, you *design* using classes and inheritance and hierarchies and 
composition and delegation... Look for any OO design introduction.

>9. Inheriting variables (only), then (always)
>    over riding their values in the sub-classes
>    doesn't save memory.

I don't understand this. You can save some memory if you declare default 
values for attributes inside the class (*not* assigning them to self), As 
far as they are never changed, they are shared by all instances. Is this 
what you mean?

class Example:
     x = 1

class Example2(Example):
     x = 2

a = Example2()
print a.x       # prints 2
b = Example2()
print b.x       # prints 2; both refer to the same shared attribute
a.x = 3 # now 'a' contains its own instance attribute
print a.x       # prints 3


Gabriel Genellina
Softlab SRL





More information about the Python-list mailing list