How to initialize instances of subclass of 'str'?

Tim Peters tim.peters at gmail.com
Sat Aug 7 00:51:47 EDT 2004


[Kenneth McDonald]
> I'm attempting to create a subclass of 'str' that I can abitrarily
> initialize at creation time. As an illustration, this gives the
> flavor of what I'm trying to do:
>
> class AlwaysLower(str):
>   def __init__(self, s):
>      str.__init__(self, s.lower())
>
> The idea is that an AlwaysLower instance should be a string
> which is always lowercase; AlwaysLower('A') -> 'a',
> AlwaysLower('b') -> 'b', etc. (Of course, the resultant
> instances are not _just_ strings, but since they are
> subclasses of str, they can be treated and viewed as strings,
> as I implicitly do above.)
>
> Unfortunately, the above code doesn't work; the resultant
> instance's string value is always s, i.e. the call to
> str.__init__ has no effect.

That's correct.  Objects of type str are immutable, so by the time
self exists (as it must for __init__), it's too late to change its
value.  You want this:

class AlwaysLower(str):
    def __new__(cls, value):
        return str.__new__(cls, value.lower())

Note that __new__ doesn't take a "self" argument -- in effect, it's
responsible for *creating* "self".  Instead it's passed the desired
result class.  __new__ *can* return an object of any type, but it's
most useful most often if it honors the request to return an object of
the passed-in class.

Give the above,

>>> a = AlwaysLower('AbC')
>>> type(a)
<class '__main__.AlwaysLower'>
>>> a
'abc'
>>> 

> ...
> Anyone know of good examples of how to subclass builtins?

Lib/test/test_descr.py has many examples.  I don't get into value
judgments about "good" <wink>.



More information about the Python-list mailing list