extending an existing class without inhertance

sismex01 at hebmex.com sismex01 at hebmex.com
Tue Jan 7 18:52:53 EST 2003


> From: Martin Schmettow
> Sent: Tuesday, January 07, 2003 10:25 AM
> 
> Hi anybody.
> 
> I am working on a script which uses several XML techniques (building 
> DOM,XSLT). For building the DOM I started using the xml.dom module.
> This module implements the setAttribute() method on element nodes.
> For some reasons I have to switch to the Ft.Xml.Domlette 
> implementation, where the setAttribute() is missing.
> Extending the class by inheritance is obvious but seems not 
> practical in this case, because a lot is done by Factories, which
> you cant just tell to produce MyElement instead of Element.
> The easiest solution would be to enhance the existing class by just 
> adding the method. I did this several times in Perl (in a 
> former life, of course).
> Can anybody tell me the Python way to do it. Other solutions 
> are welcome as well.
> 
> CU
> Martin.
>

Greetings Martin, and a Happy Knew Yeer also. :-)

What you're asking is quite doable, and simple, in Python.
Let me explain by example. Let's take a simple class where
we want to add a simple (originally non-existant) method.

>>>
>>> class Duck:
	def __init__(self, name):
		self.name = name
	def __str__(self):
		return "<%s instance '%s' at %s>" % \
		       (self.__class__.__name__, self.name, hex(id(self)))
	__repr__ = __str__

>>> d1 = Duck("Donald")
>>> d2 = Duck("Daffy")
>>> d1, d2
(<Duck instance 'Donald' at 0xb16e00>, <Duck instance 'Daffy' at 0xb19fb0>)
>>>

So we have a class which returns 'self's info upon calling
it's __str__ method. Simple.

Now, let's define a function which print's out --not returns--
the information about an instance.  It's like, but not quite,
__str__. :-)

>>>
>>> def Identify(duck):
	print "%s of name '%s', and identity %s" % \
	      (duck.__class__.__name__, duck.name, hex(id(duck)))

>>> Identify(d1)
Duck of name 'Donald', and identity 0xb16e00
>>> Identify(d2)
Duck of name 'Daffy', and identity 0xb19fb0
>>>

So it's simple-minded; this is a simple example. :-)
Now, let's convert this ordinary function into a method,
which is callable from any instance.

First, let's verify that this method doesn't exist:

>>>
>>> d1.Identify()
Traceback (most recent call last):
  File "<pyshell#55>", line 1, in ?
    d1.Identify()
AttributeError: Duck instance has no attribute 'Identify'
>>>

Now, in order to "bind" this function to a class method,
we assign it to the class object, as an attribute:

>>>
>>> d1.__class__.Identify = Identify
>>> del Identify
>>>

I deleted it from the global (module) namespace, just
to be a bit more explicit about the original function
not existing anymore:

>>>
>>> Identify(d1)
Traceback (most recent call last):
  File "<pyshell#60>", line 1, in ?
    Identify(d1)
NameError: name 'Identify' is not defined
>>> 


So now, we try out the function, now bound as an
instance method of the Duck class.  Although we
didn't actually assign it to "Duck.Identify",
remember that d1.__class__ is Duck.


>>> 
>>> d1.Identify()
Duck of name 'Donald', and identity 0xb16e00
>>> 
>>> d2.Identify()
Duck of name 'Daffy', and identity 0xb19fb0
>>>

Nice, eh? :-)

But remember, all instances of this class share the
same class object.

The only requirement, is that 'self' always be the
first argument to the new method.

Good luck, hope this helps. :-)

-gustavo





More information about the Python-list mailing list