[Tutor] Dumb Subclassing question

Kent Johnson kent_johnson at skillsoft.com
Thu Aug 5 16:51:27 CEST 2004


Andy,

There is a way to do this by replacing path.__new__(). The __new__ method 
of a class is a factory that returns the actual instance object that will 
eventually be returned by the call to the class itself. By replacing 
__new__ you can return a class of a different type.

I'm not sure this is a good design. A path to a directory should not have 
mp3 accessors, and an object representing an MP3 file doesn't need a 
files() method. I think Rich Krauter's approach of making an MP3 class that 
wraps a path to a file is probably a better design.

But you raise an interesting challenge which I couldn't resist. Here is a 
short program that munges path() so it actually returns an instance of a 
subclass of path:

from path import path

# Here is the new subclass
class MyPath(path):
     def coolStuff(self):
         print 'It works!'

# Remember the old __new__ so we can delegate to it
originalNew = path.__new__

# This is going to be the new path.__new__. It will return an instance of 
MyPath
def newNew(cls, *args, **kwds):
     return originalNew(MyPath, *args, **kwds)

# Replace path.__new__ with our new version
path.__new__ = staticmethod(newNew)

# Try it out
p = path("C:")
print type(p)
p.coolStuff()

f = p.files()
print f[0]
print type(f[0])

Running this program prints
<class '__main__.MyPath'>
It works!
C:.DS_Store
<class '__main__.MyPath'>


You could change newNew so it looks at the arguments it is passed and only 
creates a MyPath if the path has a particular form, e.g. ends with '.mp3'. 
To do this you would call originalNew(path, *args, **kwds) when you want a 
plain path. You can read more about overriding __new__ here: 
http://www.python.org/2.2.1/descrintro.html#__new__

I hope I haven't gone beyond what is appropriate for this list - this is 
definitely advanced stuff. But it is a good chance for me to learn too!

Kent

At 10:38 AM 8/5/2004 +0100, Andy Baker wrote:
>Hi all,
>
>Please bear with me as I might have this hopelessly muddled. My attempts to
>learn OO through simple cases never turn out that simple...
>
>I, like everyone else in the universe, am writing a prog to manipulate and
>organize mp3's...
>
>The idea was to base it on Jason Orendorff 'path' module
>(http://www.jorendorff.com/articles/python/path/) and add some methods to
>the path object that are mp3 specific.
>
>So I subclass the 'path' object as 'mp3path' and add some of my own methods.
>
>Several of the methods in the original 'path' return more path objects so
>the methods I inherit from path also return path objects. I want my new
>methods to act on the returned objects.
>
>An example:
>
>myPath.files() returns a list of path objects
>
>I have added a new method ID3tag to my MP3path class
>I want myMP3path.files to return a list of objects that can still access my
>ID3tag method.
>
>Options that have occurred to me:
>
>1. Override every method in 'path' that returns paths with a wrapper method
>that converts them into mp3paths. This seems ugly, boring and pointless.
>2. Forget subclassing and add methods directly into the path module source.
>This will be bad when a new version of 'path' comes along and also seems
>like cheating.
>3. Add methods dynamically into the path object. (Is this 'decorator'?) I
>looked at the instancemethod function in the standard library 'new' module
>and this adds methiods to instances but not to classes so I would have to do
>this for every instance.
>4. Forget the whole OO thang and just use functions. (Looking more
>attractive by the minute ;-)
>
>Am I being thick here? What's the proper way to do this? I can see a similar
>situation happeneing if I ever subclass 'string' or suchlike.
>
>_______________________________________________
>Tutor maillist  -  Tutor at python.org
>http://mail.python.org/mailman/listinfo/tutor



More information about the Tutor mailing list