How to initialize instances of subclass of 'str'?

  • Thread starter Kenneth McDonald
  • Start date
K

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.

I realize that I could write a function to do this, but there
are other reasons I want to subclass str. I also realize
I could have a function call AlwaysLower with a lowercase
argument, but I find that inelegant.

I've also tried messing around with __new__, but
gotten only runtime exceptions for my troubles :).
At the moment, what's really stumping me isn't so much
how to do this, but more the mechanism by which 's' is
being used to initialize the string. It's not being passed
by __init__, so how is it being passed? __new__? As
I say, I couldn't get anywhere with that.

Anyone know of good examples of how to subclass builtins?

Thanks,
Ken McDonald
 
T

Tim Peters

[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,
...
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>.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top