473,809 Members | 2,769 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

My Experiences Subclassing String

I recently went through a bit of a headache trying to subclass
string.... This is because the string is immutable and uses the
mysterious __new__ method rather than __init__ to 'create' a string.
To those who are new to subclassign the built in types, my experiences
might prove helpful. Hopefully not too many innacuracies :-)

I've just spent ages trying to subclass string.... and I'm very proud
to say I finally managed it !

The trouble is that the string type (str) is immutable - which means
that new instances are created using the mysterious __new__ method
rather than __init__ !! :-) You still following me.... ?

SO :

class newstring(str):
def __init__(self, value, othervalue):
str.__init__(se lf, value)
self.othervalue = othervalue

astring = newstring('hell o', 'othervalue')

fails miserably. This is because the __new__ method of the str is
called *before* the __init__ value.... and it says it's been given too
many values. What the __new__ method does is actually return the new
instance - for a string the __init__ method is just a dummy.

The bit I couldn't get (and I didn't have access to a python manual at
the time) - if the __new__ method is responsible for returning the new
instance of the string, surely it wouldn't have a reference to self;
since the 'self' wouldn't be created until after __new__ has been
called......

Actually thats wrong - so, a simple string type might look something
like this :

class newstring(str):
def __new__(self, value):
return str.__new__(sel f, value)
def __init__(self, value):
pass

See how the __new__ method returns the instance and the __init__ is
just a dummy.
If we want to add the extra attribute we can do this :
class newstring(str):
def __new__(self, value, othervalue):
return str.__new__(sel f, value)
def __init__(self, value, othervalue):
self.othervalue = othervalue

The order of creation is that the __new__ method is called which
returns the object *then* __init__ is called. Although the __new__
method receives the 'othervalue' it is ignored - and __init__ uses it.
In practise __new__ could probably do all of this - but I prefer to
mess around with __new__ as little as possible ! I was just glad I got
it working..... What it means is that I can create my own class of
objects - that in most situations will behave like strings, but have
their own attributes. The only restriction is that the string value is
immutable and must be set when the object is created. See the
excellent path module by Jason Orendorff for another example object
that behaves like a string but also has other attributes - although it
doesn't use the __new__ method; or the __init__ method I think.

Regards,

Fuzzy

Posted to Voidspace - Techie Blog :
http://www.voidspace.org.uk/voidspace/index.shtml
Experiences used in the python modules at :
http://www.voidspace.org.uk/atlantib...thonutils.html
Jul 18 '05 #1
2 8907
"Fuzzyman" <mi*****@foord. net> wrote in message
news:80******** *************** ***@posting.goo gle.com...
I recently went through a bit of a headache trying to subclass
string.... This is because the string is immutable and uses the
mysterious __new__ method rather than __init__ to 'create' a string.
To those who are new to subclassign the built in types, my experiences
might prove helpful. Hopefully not too many innacuracies :-)
<snip>
The bit I couldn't get (and I didn't have access to a python manual at
the time) - if the __new__ method is responsible for returning the new
instance of the string, surely it wouldn't have a reference to self;
since the 'self' wouldn't be created until after __new__ has been
called......

Actually thats wrong - so, a simple string type might look something
like this :

class newstring(str):
def __new__(self, value):
return str.__new__(sel f, value)
def __init__(self, value):
pass

See how the __new__ method returns the instance and the __init__ is
just a dummy.
If we want to add the extra attribute we can do this :
class newstring(str):
def __new__(self, value, othervalue):
return str.__new__(sel f, value)
def __init__(self, value, othervalue):
self.othervalue = othervalue

The order of creation is that the __new__ method is called which
returns the object *then* __init__ is called. Although the __new__
method receives the 'othervalue' it is ignored - and __init__ uses it.

<snip>

Fuzzy -

I recently went down this rabbit hole while trying to optimize Literal
handling in pyparsing. You are close in your description, but there is one
basic concept that I think still needs to be sorted out for you.

Think of __new__ as a class-level factory method, not an instance method.
That first argument that you passed to your example as 'self' is not the
self instance, it is the class being new'ed. By luck, even though you
called it 'self', you passed it to str.__new__ where the class argument is
supposed to go, so everything still worked.

The canonical/do-nothing __new__ method looks like this:

class A(object):
def __new__(cls,*ar gs):
return object.__new__( cls)

There's nothing stopping you from looking at the args tuple to see if you
want to do more than this, but in truth that's what __init__ is for.

Here's a sample of using __new__ to return a different class of object,
depending on the initialization arguments:

class SpecialA(object ):
pass

class A(object):
def __new__(cls,*ar gs):
print cls,":",args
if len(args)>0 and args[0]==2:
return object.__new__( SpecialA)
return object.__new__( cls)

obj = A()
print type(obj)
obj = A(1)
print type(obj)
obj = A(1,"test")
print type(obj)
obj = A(2,"test")
print type(obj)

gives the following output:

<class '__main__.A'> : ()
<class '__main__.A'>
<class '__main__.A'> : (1,)
<class '__main__.A'>
<class '__main__.A'> : (1, 'test')
<class '__main__.A'>
<class '__main__.A'> : (2, 'test')
<class '__main__.Speci alA'>
HTH,
-- Paul
Jul 18 '05 #2
"Paul McGuire" <pt***@austin.r r._bogus_.com> wrote in message news:<51******* ************@fe 2.texas.rr.com> ...
[reluctant snip...]

class SpecialA(object ):
pass

class A(object):
def __new__(cls,*ar gs):
print cls,":",args
if len(args)>0 and args[0]==2:
return object.__new__( SpecialA)
return object.__new__( cls)

obj = A()
print type(obj)
obj = A(1)
print type(obj)
obj = A(1,"test")
print type(obj)
obj = A(2,"test")
print type(obj)

gives the following output:

<class '__main__.A'> : ()
<class '__main__.A'>
<class '__main__.A'> : (1,)
<class '__main__.A'>
<class '__main__.A'> : (1, 'test')
<class '__main__.A'>
<class '__main__.A'> : (2, 'test')
<class '__main__.Speci alA'>
HTH,
-- Paul


Thanks Paul, that was helpful and interesting.
I've posted the following correction to my blog :

Ok... so this is a correction to my post a couple of days ago about
subclassing the built in types (in python).

I *nearly* got it right. Because new is the 'factory method' for
creating new instances it is actually a static method and *doesn't*
receive a reference to self as the first instance... it receives a
reference to the class as the first argument. By convention in python
this is a variable named cls rather than self (which refers to the
instance itself). What it means is that the example I gave *works*
fine, but the terminology is slightly wrong...

See the docs on the new style classes unifying types and classes. Also
thanks to Paul McGuire on comp.lang.pyton for helping me with this.

My example ought to read :
class newstring(str):
def __new__(cls, value, *args, **keywargs):
return str.__new__(cls , value)
def __init__(self, value, othervalue):
self.othervalue = othervalue

See how the __new__ method collects all the other arguments (using the
*args and **keywargs collectors) but ignores them - they are rightly
dealt with by __init__. You *could* examine these other arguments in
__new__ and even return an object that is an instance of a different
class depending on the parameters - see the example Paul gives...

Get all that then ? :-)
Jul 18 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1562
by: Mizrandir | last post by:
I'd like to subclass numarray's array. I'd like to add some methods and override others like __init__. I don't know how to do this and haven't found help searching the manual or the web, can someone help? For example imagine I just want to do something as simple as making a subclass "NewClass" with the __init__ method overridden so that the behaviour would be: >>> a = NewClass(2) >>> print a
2
5166
by: BJörn Lindqvist | last post by:
A problem I have occured recently is that I want to subclass builtin types. Especially subclassing list is very troublesome to me. But I can't find the right syntax to use. Take for example this class which is supposed to be a representation of a genome: class Genome(list): def __init__(self): list.__init__(self) self = ....
11
3480
by: Brent | last post by:
I'd like to subclass the built-in str type. For example: -- class MyString(str): def __init__(self, txt, data): super(MyString,self).__init__(txt) self.data = data
2
6541
by: Laura Martignas | last post by:
Hi everybody I'm trying to subclass Winamp's main window in order to develop a software which will interact with Winamp. For testing, I'm trying to intercept the closing of this window via WM_CLOSE, by showing a MessageBox, but it doesn't work althoug the code seems to be correct. Do you notice a mistake ? My test program contains a form with 2 buttons : one button to activate subclassing, and the second button to desactivate it.
0
1903
by: Dijkstra | last post by:
Hi! I am writing a program in which I need to keep track of how many objects of a given class exists at a time. The task is to do it using templates. The objects to be counted are of the class Note: class Note : public Countable<Note> { private: ... public: Note(); Note(double points, int time); Note(double points, string time); ~Note();
2
1236
by: Paulo da Silva | last post by:
Hi! What's wrong with this way of subclassing? from datetime import date class MyDate(date): def __init__(self,year,month=None,day=None): if type(year) is str: # The whole date is here as a string
16
2082
by: manatlan | last post by:
I've got an instance of a class, ex : b=gtk.Button() I'd like to add methods and attributes to my instance "b". I know it's possible by hacking "b" with setattr() methods. But i'd like to do it with inheritance, a kind of "dynamic subclassing", without subclassing the class, only this instance "b" ! In fact, i've got my instance "b", and another class "MoreMethods"
5
2535
by: Ray | last post by:
Hi all, I am thinking of subclassing the standard string class so I can do something like: mystring str; .... str.toLower (); A quick search on this newsgroup has found messages by others
13
1463
by: =?Utf-8?B?QmV0aA==?= | last post by:
Hello. I'm trying to figure out how to create subclasses with properties specific to the subclass and so far it isn't going well. Right now I have a class with an enum representing the type. The class has all the properties specific to all the types, but what I want instead is to move those properties to subclasses specific to each type. I have code like this:
0
9721
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9600
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10633
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10376
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10375
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10114
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9198
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6880
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
3860
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.