Type subclassing: bug or feature

Bengt Richter bokr at oz.net
Thu Jun 13 21:58:14 EDT 2002


On 13 Jun 2002 23:24:09 +0200, Chris Liechti <cliechti at gmx.net> wrote:

>aahz at pythoncraft.com (Aahz) wrote in news:aeau48$111$1 at panix1.panix.com:
>
>> Consider the following code:
>> 
>> class MyStr(str):
>>     def contains(self, value):
>>         return self.find(value) >= 0
>> 
>> s = MyStr("hello, world!")
>> s = s.capitalize()
>> if s.contains('Hello'):
>>     print "Found it!"
>> 
>> It fails with an AttributeError when it calls s.contains(), because
>> s.capitalize() returned a str instead of a MyStr.  Anyone want to take a
>> whack at defending this as the correct behavior?
>
>solving this at the C level would require patching many stingobject factory 
>functions... e.g. PyString_FromStringAndSize for capitalize(). but it would 
>indeed be desireable.
>
>i think it would like to have a even more genral mechanism. i would like to 
>have a possibility to replace the builtin type. e.g. i could replace the 
>builtin "str" and all strings from now on would be instaces of my class. 
>but that's clearly impossible in the current implementation.
>
><hacker warning>
>like Bengt already sugested just automated ;-) ...
>
>>>> class mstr(str):
>... 	for name,m in str.__dict__.items():
>... 		if type(m) == type(str.find):
>... 			exec """def %s(*args, **kwargs):
>... 					q = str.%s(*args, **kwargs)
>... 					if type(q) is str: return mstr(q)
>... 					else: return q\n""" % (name, name)
>... 	def __contains__(self, other):
>... 		return str.find(self, other) >= 0
>... 	
>>>> s = mstr("hello")
>>>> type(s.capitalize())
><class '__main__.mstr'>
>>>> 'll' in s.capitalize()
>1
></hacker warning>
>
Interesting way to go if you can't know except dynamically at run time
what types base class methods will return.

I don't know how you'd fully generalize this process though, and it
seems a shame to have to wrap everything in an extra layer. It would
be nice to be able to specify coercions in the subclass in a way that
base class methods could access quickly to check whether to call a coercion
routine on a result, e.g.,

    __coercions__ = (str, mstr), (bool, No_Yes)  # just as example with several coercions

Also str.split could even access this,  and produce a list of MyStr substrings.
And also deeper bases' methods could check on self.__coercions__

Just OTTOMH, so not very thought through ;-)

BTW, I just thought of a 'where' keyword for 'for' e.g., the above for would become

    for name,m in str.__dict__.items() where type(m) == type(str.find):

sort of like sql select ... where ... or the list comprehension if.

Regards,
Bengt Richter



More information about the Python-list mailing list