function that modifies a string

G

greenflame

I want to make a function that does the following. I will call it
thefunc for short.
'||Char>>'

I tried the following

def thefunc(s):
s = "||" + s + ">>"

The problem is that if I look at the string after I apply the function
to it, it is not modified. I realized that I am having issues with the
scope of the variables. The string in the function, s, is local to the
function and thus I am not changing the string that was inputed, but a
copy. I cannot seem to figure out how to get what I want done. Thank
you for your time.
 
J

Jason

greenflame said:
I want to make a function that does the following. I will call it
thefunc for short.

'||Char>>'

I tried the following

def thefunc(s):
s = "||" + s + ">>"

The problem is that if I look at the string after I apply the function
to it, it is not modified. I realized that I am having issues with the
scope of the variables. The string in the function, s, is local to the
function and thus I am not changing the string that was inputed, but a
copy. I cannot seem to figure out how to get what I want done. Thank
you for your time.

You cannot do what you are trying to do directly. Strings are
immutable objects. Once a string is created, that string cannot be
modified. When you operate on a string, you produce a different
string. Functions which operate on a string should return their value:
.... return '||' + s + '>>'
....'||Char>>'

There /are/ a few hacks which will do what you want. However, if you
really need it, then you probably need to rethink your program design.
Remember, you can't change a string since a string is immutable! You
can change a variable to bind to another string. In the following
example, s gets rebound to the new string while t keeps the original
string value:
.... globalDict = globals()
.... globalDict[varName] = '||' + globalDict[varName] + '>>'
.... return
....'Char'

Further note that this only affects variables in the global scope. I
hope this helps!

--Jason
 
P

placid

greenflame said:
I want to make a function that does the following. I will call it
thefunc for short.

'||Char>>'

I tried the following

def thefunc(s):
s = "||" + s + ">>"

The problem is that if I look at the string after I apply the function
to it, it is not modified. I realized that I am having issues with the
scope of the variables. The string in the function, s, is local to the
function and thus I am not changing the string that was inputed, but a
copy. I cannot seem to figure out how to get what I want done. Thank
you for your time.

quick hack

def thefunc(s):
return s = "||" + s + ">>"
||hello>>


--Cheers
 
G

greenflame

Jason said:
You cannot do what you are trying to do directly. Strings are
immutable objects. Once a string is created, that string cannot be
modified. When you operate on a string, you produce a different
string. Functions which operate on a string should return their value:
... return '||' + s + '>>'
...'||Char>>'

There /are/ a few hacks which will do what you want. However, if you
really need it, then you probably need to rethink your program design.
Remember, you can't change a string since a string is immutable! You
can change a variable to bind to another string. In the following
example, s gets rebound to the new string while t keeps the original
string value:
... globalDict = globals()
... globalDict[varName] = '||' + globalDict[varName] + '>>'
... return
...'Char'

Further note that this only affects variables in the global scope. I
hope this helps!

--Jason

Ok so let me see if I understand. The globalDict is just a dictionary
containing the name of the global variables as the keys and their
values as the values of the dictionary? Thus the inputed variable is
treated like a global variable?
 
S

Simon Forman

greenflame said:
Jason said:
There /are/ a few hacks which will do what you want. However, if you
really need it, then you probably need to rethink your program design.
Remember, you can't change a string since a string is immutable! You
can change a variable to bind to another string. In the following
example, s gets rebound to the new string while t keeps the original
string value:
def changeString(varName):
... globalDict = globals()
... globalDict[varName] = '||' + globalDict[varName] + '>>'
... return
...
s = 'Char'
t = s
changeString('s')
s '||Char>>'
t
'Char'

Further note that this only affects variables in the global scope. I
hope this helps!

--Jason

Ok so let me see if I understand. The globalDict is just a dictionary
containing the name of the global variables as the keys and their
values as the values of the dictionary? Thus the inputed variable is
treated like a global variable?

The answer to your first question is yup! You've got it. That's what
the globals() function returns. (There is also a function locals()
that returns a similar dict but for locals.)

The answer to your second question is no. The inputed *name* (the
changeString() function must be passed a string, not a variable) must
be the name of an object in the global scope for the function to work.

You almost certainly want to use a function like the thefunc() function
that Jason posted.

One other thing, you could define it like so:

def thefunc(s):
return '||%s>>' % s


Peace,
~Simon
 
S

Steven D'Aprano

quick hack

def thefunc(s):
return s = "||" + s + ">>"

||hello>>

That's not a quick hack. That's the right way to solve the problem.

Of course, another right way would be to have mutable strings in Python.
I understand why strings need to be immutable in order to work with dicts,
but is there any reason why (hypothetical) mutable strings should be
avoided in situations where they aren't needed as dictionary keys? Python
has mutable lists and immutable tuples, mutable sets and immutable frozen
sets, but no mutable string type.
 
S

Sion Arrowsmith

Steven D'Aprano said:
Of course, another right way would be to have mutable strings in Python.

What significant advantage would mutable strings have over StringIO
and wrapping list manipulation in list(s) and ''.join(l). Other than
that pleasing symmetry with sets/frozensets etc.
 
D

Diez B. Roggisch

Of course, another right way would be to have mutable strings in Python.
I understand why strings need to be immutable in order to work with dicts,
but is there any reason why (hypothetical) mutable strings should be
avoided in situations where they aren't needed as dictionary keys? Python
has mutable lists and immutable tuples, mutable sets and immutable frozen
sets, but no mutable string type.

What's wrong about arrays of chars?

Diez
 
T

tac-tics

Diez said:
What's wrong about arrays of chars?

Arrays of chars are dangerous. If you insist, use Python lists of
Python "chars" (strings of length 1).

If you really want a mutable string type, there's nothing in python
that keeps you from writting one yourself. You just have to be more
careful than you would be in C++, because your MutableString type would
always be passed by reference to functions, and so you'd have to be
very careful to copy it unless you want weird, unfindable bugs to crop
up in your program.
 
D

Diez B. Roggisch

tac-tics said:
Arrays of chars are dangerous. If you insist, use Python lists of
Python "chars" (strings of length 1).

Why are they more dangerous than a self-written mutable string?
If you really want a mutable string type, there's nothing in python
that keeps you from writting one yourself. You just have to be more
careful than you would be in C++, because your MutableString type would
always be passed by reference to functions, and so you'd have to be
very careful to copy it unless you want weird, unfindable bugs to crop
up in your program.

I don't buy that. You are right about the dangers - but I fail to see where
C++ gives you any protection from these pitfalls. And what disqualifies an
array of characters in python that exists and has all the methods I can
think of for a mutable string.

Regards,

Diez
 
S

Steven D'Aprano

What significant advantage would mutable strings have over StringIO
and wrapping list manipulation in list(s) and ''.join(l). Other than
that pleasing symmetry with sets/frozensets etc.

Some algorithms (e.g. genetic algorithms) have natural implementations
in terms of mutable strings.

StringIO is more like a kind of file than a kind of string. It has no
methods for upper/lowercase, searching, etc. While files do have random
access, they don't have random access insertion and deletion like lists or
hypothetical mutable strings, so StringIO is no replacement at all.
 
S

Steven D'Aprano

What's wrong about arrays of chars?

Nice suggestion. However, I should point out that the methods available to
array.array('c') are quite limited compared to the methods available to
strings. Still, it would make a good basis to start with, and far better
than my initial thought of a list of chars.
 
J

Jason

Simon said:
greenflame said:
Jason said:
There /are/ a few hacks which will do what you want. However, if you
really need it, then you probably need to rethink your program design.
Remember, you can't change a string since a string is immutable! You
can change a variable to bind to another string. In the following
example, s gets rebound to the new string while t keeps the original
string value:

def changeString(varName):
... globalDict = globals()
... globalDict[varName] = '||' + globalDict[varName] + '>>'
... return
...
s = 'Char'
t = s
changeString('s')
s
'||Char>>'
t
'Char'

Further note that this only affects variables in the global scope. I
hope this helps!

--Jason

Ok so let me see if I understand. The globalDict is just a dictionary
containing the name of the global variables as the keys and their
values as the values of the dictionary? Thus the inputed variable is
treated like a global variable?

The answer to your first question is yup! You've got it. That's what
the globals() function returns. (There is also a function locals()
that returns a similar dict but for locals.)

The answer to your second question is no. The inputed *name* (the
changeString() function must be passed a string, not a variable) must
be the name of an object in the global scope for the function to work.

You almost certainly want to use a function like the thefunc() function
that Jason posted.

One other thing, you could define it like so:

def thefunc(s):
return '||%s>>' % s


Peace,
~Simon

Certainly. I do want to add a warning: do not modify the dictionary
returned from locals(). Please note the warning given at
"http://docs.python.org/lib/built-in-funcs.html#l2h-45".

--Jason
 
T

tac-tics

What's wrong about arrays of chars?
Why are they more dangerous than a self-written mutable string?

I didn't say that. I meant that arrays in the C++ sense are dangerous.

I don't buy that. You are right about the dangers - but I fail to see where
C++ gives you any protection from these pitfalls. And what disqualifies an
array of characters in python that exists and has all the methods I can
think of for a mutable string.

C++ offers pass by value options. That makes it so you never need to
worry about messing up data that doesn't belong to you unless you
explicitly pass by reference. Python doesn't do this for you. Thus, a
mutable string class in Python requires a great deal more care since
you need to make copies of every string in every function in order to
prevent changes in one object's string from affecting another.
 
F

Fredrik Lundh

tac-tics said:
I didn't say that. I meant that arrays in the C++ sense are dangerous.

so what do you think Python's string type uses on the inside ?
C++ offers pass by value options. That makes it so you never need to
worry about messing up data that doesn't belong to you unless you
explicitly pass by reference. Python doesn't do this for you. Thus, a
mutable string class in Python requires a great deal more care since
you need to make copies of every string in every function in order to
prevent changes in one object's string from affecting another.

and that would be different from any other mutable Python type in
exactly what way ?

</F>
 
D

Diez B. Roggisch

Arrays of chars are dangerous. If you insist, use Python lists of
I didn't say that. I meant that arrays in the C++ sense are dangerous.

So what? Python's arrays are backed by arrays of the type they have,
whereas lists are represented by arrays of python objects. Both arrays
of some kind. Both hide this behind a convenient API whcih don't put any
responsibility on the programmer's shoulder. Now I ask again: where is
that dangerous, or more dangerous than writing your own mutable string?
C++ offers pass by value options. That makes it so you never need to
worry about messing up data that doesn't belong to you unless you
explicitly pass by reference. Python doesn't do this for you. Thus, a
mutable string class in Python requires a great deal more care since
you need to make copies of every string in every function in order to
prevent changes in one object's string from affecting another.

While you are technically correct, it strikes me odd that someone uses
mutable strings in a scenario where he also wants copy-semantics for
pass-by-value. That is plain stupid: create O(n) complexity to achieve
what immutable strings buy you for O(1).

So: Yes, mutable strings are dangerous. Use them only when their
benefits outweigh their risks. But you argumentation regarding C++ is
odd to say the least. Especially since the cited call-by-value semantics
doesn't come for free - designing and implementing assignment operators
and copy-constructors is a daunting task in itself.

And if you WANT to use mutable strings with a call-by-value semantic in
python, a simple decorator that scans arguments for mutable strings
could help you there.

Diez
 
S

Steven D'Aprano

On Mon, 10 Jul 2006 19:30:09 +0200, Diez B. Roggisch wrote:

[snip]
So: Yes, mutable strings are dangerous.

I'm sorry, perhaps I'm being slow today, but just why are they dangerous?
More dangerous than, say, mutable lists and mutable dicts? Unless I'm
missing something, the worst that can happen is that people will write
inefficient code, and they'll be caught out by the same sort of things
that surprise newbies about lists. E.g. using a list as a default value
in function definitions.

Use them only when their benefits outweigh their risks.

That goes without saying :)
 
D

Diez B. Roggisch

I'm sorry, perhaps I'm being slow today, but just why are they dangerous?
More dangerous than, say, mutable lists and mutable dicts? Unless I'm
missing something, the worst that can happen is that people will write
inefficient code, and they'll be caught out by the same sort of things
that surprise newbies about lists. E.g. using a list as a default value
in function definitions.

Well, they certainly aren't more dangerous than other mutable objects in
python. But in comparison to only dealing with immutable collections, using
immutable strings never made something impossible or even hard to do - at
least for me. Sometimes a bit harder to do efficiently.

So - the overall danger of mutability can be avoided with immutable strings
pretty neat, and thus one should (or could) go without them.

Regards,

Diez
 

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
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top