[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