What is the status of the __subclasses__ method?

Ruud de Jong ruud.de.jong at consunet.nl
Sat Feb 28 05:50:01 EST 2004


Michael Hudson schreef:

> Ruud de Jong <ruud.de.jong at consunet.nl> writes:
> 
> 
>>The question I have is: how safe / future proof / portable is the
>>use of the __subclasses__ method that exists for new-style classes?
> 
> 
> Hmm.  I think it's unlikely to go away.
> 
> 
>>When I searched python.org for "__subclasses__" I found
>>some more information. The __subclasses__ method appears
>>to exist to allow modifications of the superclass to be
>>percolated down to its children, mainly for speed reasons,
>>if I understand Tim Peter's explanation correctly
>>(http://mail.python.org/pipermail/python-list/2003-August/176360.html). 
> 
> 
> Yep.

What I wanted to avoid is that I would rely on something that is
not part of the Python *language*, but rather of a Python
*implementation*. But then, the distinction between these two
is not always clear -- if a construct is present in every
implementation, what is the difference with it being a part
of the language?

Well, raising the question is answering it -- as long as a
construct is not officially part of the language, that construct
can in principle change or disappear if the language maintainers
find that necessary.


>>I also found several warnings that the __subclasses__ method only
>>returns classes that have been accessed previously (which would
>>defeat my purpose)
> 
> 
> Hum, you're being overly paranoid here.  Python defined types are
> PyType_Ready-ed as soon as they are created.
> 

Well, I guess that such cautious behavior has become sort of
second nature for me -- a consequence of having worked some
twenty years on a huge software system (think multi-million lines
of C code), with thousands of colleagues adding, deleting and
modifying code simultaneously. In spite of strict processes and
procedures, too often somebody would make themselves dependent on
some construct in another part of the system that was never
meant for public usage. And when that construct was modified
to add e.g. new functionality or for performance improvement,
all hell would break loose -- because it would break the
functionality that "illegally" used the construct (and that
had been working fine for the customers)

With this conditioning I tend to be *very* careful about
using undocumented features, like __subclasses__.

Anyway, if I understand you correctly, as long as the subclasses
are implemented in Python, they will be known to their parent
immediately. And from your other remarks I get the
impression that the __subclasses__ method is a rather permanent
feature in every Python implementation.

> 
>>So again, my question. Is it safe to use the __subclasses__
>>method for the purpose I described above? 
> 
> 
> Well, I can't see into the future, but I'd feel secure using it.
> 
> I'm not sure what you describe is a very tasteful use of it though...
> 
Well, not being a native english speaker, I don't quite know how to
interpret this latter remark. Please elaborate. Are you objecting
to the use of the __subclasses__ method? Or to the general mechanism
I described? Or maybe I really am paranoid, and I am reading things
that aren't there :-)

Here is the essence of the use of __subclasses__ in the application
I referred to. Note that is a variant of the Chain-of-Responsibility
pattern, applied to the Factory Method. I know that I abused the
NotImplementedError -- in the actual application it is a custom-
defined exception. But for illustration purposes I wanted to avoid
such non-essential details.

 >>> class Event(object):
	def __new__(cls, line):
		for subclass in cls.__subclasses__():
			try:
				return subclass.__new__(subclass, line)
			except NotImplementedError:
				continue
		raise NotImplementedError

	
 >>> class MsgEvent(Event):
	pass

 >>> class IncomingMsgEvent(MsgEvent):
	def __new__(cls, line):
		if line.startswith('RCV:'):
			return object.__new__(cls)
		raise NotImplementedError

	
 >>> class OutgoingMsgEvent(MsgEvent):
	def __new__(cls, line):
		if line.startswith('SND:'):
			return object.__new__(cls)
		raise NotImplementedError

	
 >>> x = Event('RCV: blah blah')
 >>> x
<__main__.IncomingMsgEvent object at 0x00AD2D30>
 >>>

The thing to note is that I can add subclasses at will, and
never have to revisit the Event root class. This means better
maintainability and extensibility.

> 
>>Or would it be safer to revert to my home-grown metaclass solution?
> 
> 
> You might want to keep it around, I guess...
> 
I will. I joins my collection of APL one-liners and my FORTRAN V
preprocessor :-)

Regards,

Ruud de Jong




More information about the Python-list mailing list