You are not logged in.
[Edit: Finished code at the end of this post.]
Hey guys!,
I'm in the middle of writing a class that allows for more flexible string usage in Python (yes, it's possible).
Although Python implements strings extremely well, it's missing string mutation.
It seems as though the developers chose not to implement it (even in py3k), though for what reason, I do not know.
My problem is this; how do you re-assign the value of an object (from within the scope of a function) in a class (that inherits string properties)?
To simplify;
(class) -> string object
(class) - (function) -> modify string object
The goal is not to mutate the object (that's impossible), the goal is to re-assign the value attributed to the object.
Here is an outline;
class semi_mutable_str (str):
# define a class that inherits native str properties
def __init__(self, value):
self.str = value
def rm(self, pos):
'''Remove the character in self.str at pos.'''
new = self.str[0:pos]
new += self.str[pos+1:len(self.str)]
self.str = new
del new
return self.str
>>> variable = semi_mutable_str ("aaa aba abb bbb b a")
>>> variable
"aaa aba abb bbb b a"
>>> variable.rm(0)
>>> variable.str
"aa aba abb bbb b a"
>>> variable
"aaa aba abb bbb b a"
Note that variable.str has been appropriately changed, but when I call variable, I get what I started with.
How do I change the value that is returned when I call 'variable'?
That is my question.
Thank you very much for reading, and your time.
Regards
EDIT -> Finished Class:
#!/usr/bin/env python
# Mutable strings meet Python 2.x.
# update;
# Operator Overloading
# Faster Mutation
# More Readable/Documentated Code
# Error Handling
# More Functionality
# str Inheritance
class mstr (str):
def __init__ (self, val):
if 'zfill' not in dir(val):
self.str = repr(val)
else:
self.str = val
def __div__ (self, new):
''' / Overloading:
Input can be an array of len 2, or an int.
Case array; splice. Case int; rm.
'''
try:
if 'zfill' in dir(new):
raise SyntaxError
if len(new) != 2:
raise SyntaxError
return self.splice(new[0], new[1])
except TypeError:
if 'zfill' in dir(new):
raise SyntaxError
return self.rm(new)
def __add__ (self, new):
''' + Overloading.
Add strings.
'''
self.bak = self.str
self.str += new
return self.str
def __sub__ (self, new):
''' - Overloading.
rm_phr
'''
return self.rm_phr(new)
def __pow__ (self, new):
''' ^ Overloading.
Input can be a str or an array of len 2.
Case str; asgn. Case (int, str); ch. Case (str, int); asgn.
'''
if '__rand__' in dir(new):
raise SyntaxError
elif 'zfill' in dir(new):
return self.asgn(new)
else:
if '__rand__' in dir(new[0]):
return self.ch(new[0], new[1])
else:
return self.asgn(new[0], new[1])
def __mul__ (self, new):
''' * Overloading.
Multiply strings.
'''
self.bak = self.str
tmp = self.str
for iteration in range(0,new-1):
self.str += tmp
del tmp, new
return self.str
def rm (self, pos): # /
'''Remove the character in self.str at pos (position).
Note: m_str(s) start indexing at 0.
'''
if 0 > pos > len(self.str)-1:
raise IndexError
self.bak = self.str
new = self.str[0:pos]+self.str[pos+1:]
self.str = new
del new, pos
return self.str
def rm_phr(self, phr, new="", all=True): # -
'''Remove ALL INSTANCES of phr or char (phrase) from self.str. Leaves whitespace.
To remove whitespace, simply obj.rm_phr(' ')
(If you want to remove only the first instance, specify so by;
self.rm_phr(phr='phr', new='new', all=False)
'''
self.bak = self.str
lphr=len(phr)
if phr in self.str:
loc = self.str.find(phr)
self.str = self.purge(loc, lphr)
if all == True:
loc = self.str.find(phr)
self.rm_phr(phr=phr, new=new)
else:
del lphr, phr, new, all
return self.str
else:
del lphr, phr, new, all
return self.str
def purge(self, loc, lphr):
'''Helpher function to the recursive self.rm_phr.
Removes a chunk of self.str that
starts at loc (location) is lphr (lenght of phrase) long.
'''
if loc == 0:
new = self.str[lphr:]
else:
new = self.str[0:loc]+self.str[loc+lphr:]
return new
def asgn(self, phr, pos=0): # ^
'''Assign char/phr to self.str at pos.
The existing char will be SCOOTED TO THE RIGHT.'''
if 0 > pos > len(self.str):
raise IndexError
self.bak = self.str
if pos == 0:
new = phr+self.str
else:
new = self.str[0:pos]+phr+self.str[pos:]
self.str = new
del new, phr, pos
return self.str
def asgn_r(self, phr):
'''Assign char/phr to self.str to the right side of the string.'''
self.asgn(phr, pos=len(self.str))
del phr
return self.str
def ch(self, pos, phr): # ^
'''Change pos:lphr in self.str to phr.
The existing phr will be deleted.
'''
if 0 > pos > len(self.str)-1:
raise IndexError
lphr = len(phr)
self.bak = self.str
if pos == 0:
new = phr+self.str[lphr:]
if pos > 0:
new = self.str[0:pos]+phr+self.str[pos+lphr:]
self.str = new
del new, pos, phr, lphr
return self.str
def str_dict (self, s):
self.dict = {}
field = range(0, len(s))
for key in field:
self.dict[key] = s[key]
del field, s
return self.dict
def dict_str (self):
new = ""
for key,char in self.dict.iteritems():
new += char
self.str = new
del new
return self.str
def splice(self, beg, end): # -
'''Splice the chunk of the string specified in the params.'''
self.bak = self.str
self.str_dict(self.str)
blacklist = range(beg+1, end)
new = ""
for key,char in self.dict.iteritems():
if key not in blacklist and key != beg and key != end:
new += char
self.str_dict(new)
self.str = new
del new, beg, end
return self.str
def undo(self):
self.str = self.bak
return self.str
def __str__(self): # self
'''Overload str method __str__. '''
return self.str
Last edited by vsk (2008-07-20 02:27:10)
Offline
I think you ought to type out the words "phrase", "assign" and "remove" in the method names.
Offline
Thank you for your interest.
I have added operator overloading, so you can now do;
import str
obj = str.mstr("0123456789 ab ab")
print obj
obj / (4,6) # splice: removes obj[4:6]
print obj
obj + "new" # append
print obj
print obj / 0 # removes obj[0]
obj ** ">>>" # asgn
print obj
obj ** (3,"ooo") # change obj[3:len("ooo")] to "ooo", i.e: obj[3:6] = "ooo"
print obj
obj ** (0,"#") # change: obj[0] = "#" type of thing
obj ** ("vks", 3) # asgn: inject "vks" at obj[3]
print obj
obj - "a" # remove all instances of 'a' in obj
print obj
obj.rm_phr(phr='b', all=False) # rm first instance of 'b' in obj
print obj
obj * 2 # multiply
print obj
obj.undo()
print obj
# normal strings are left unchanged
a = "012345"
try:
a / 3
a ** "-2 -1"
except TypeError:
print;print
print "Normal string operators are left unchanged."
print "Some of the operators (+,*) are available in Python's str class."
print "However, they don't actually make the changes permanent."
Cool stuff .
In any case - my teacher says that string immutability is a security feature to prevent users from committing memory evils.
Oh well.
My code is pretty safe.
Offline