Why are strings immutable?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Brent W. Hughes

    Why are strings immutable?

    I kind of hate to have to convert a string into a list, manipulate it, and
    then convert it back into a string. Why not make strings mutable?


  • Sam Holden

    #2
    Re: Why are strings immutable?

    On Sat, 21 Aug 2004 03:26:00 GMT,
    Brent W. Hughes <brent.hughes@c omcast.net> wrote:[color=blue]
    > I kind of hate to have to convert a string into a list, manipulate it, and
    > then convert it back into a string. Why not make strings mutable?[/color]

    Not being able to use strings as dictionary keys would kind of suck :)

    --
    Sam Holden

    Comment

    • Peter Hansen

      #3
      Re: Why are strings immutable?

      Brent W. Hughes wrote:
      [color=blue]
      > I kind of hate to have to convert a string into a list, manipulate it, and
      > then convert it back into a string. Why not make strings mutable?[/color]

      It is unlikely you are doing whatever it is you need to do
      in the best way possible if you are converting to a list and
      back. What's the use case here? Can you describe what you
      need to accomplish without reference to how you think it should
      be accomplished? Maybe there's a better way...

      -Peter

      Comment

      • Byron

        #4
        Re: Why are strings immutable?

        Hi Brent,

        It is usually best to create a function in which you can
        1) pass the string to
        2) change it as needed
        3) return the modified sting back to the original caller.

        Can you tell us a little more about what you are trying to accomplish?

        Byron
        ---


        Brent W. Hughes wrote:[color=blue]
        > I kind of hate to have to convert a string into a list, manipulate it, and
        > then convert it back into a string. Why not make strings mutable?[/color]

        Comment

        • John Roth

          #5
          Re: Why are strings immutable?


          "Brent W. Hughes" <brent.hughes@c omcast.net> wrote in message
          news:chzVc.2884 37$a24.71659@at tbi_s03...[color=blue]
          > I kind of hate to have to convert a string into a list, manipulate it, and
          > then convert it back into a string. Why not make strings mutable?[/color]

          Strings are immutable because they are "value objects".
          Consult any good, recent OO design text for what a
          value object is, and why it should be immutable.

          That said, it would be useful to have a
          string buffer object that could be changed.

          John Roth[color=blue]
          >
          >[/color]


          Comment

          • Christos TZOTZIOY Georgiou

            #6
            Re: Why are strings immutable?

            On Sat, 21 Aug 2004 11:34:54 -0400, rumours say that "John Roth"
            <newsgroups@jhr othjr.com> might have written:

            [<snip> strings are immutable because...]
            [color=blue]
            >That said, it would be useful to have a
            >string buffer object that could be changed.[/color]

            array.array('c' ) is a close substitute.
            --
            TZOTZIOY, I speak England very best,
            "Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek

            Comment

            • Leif K-Brooks

              #7
              Re: Why are strings immutable?

              John Roth wrote:[color=blue]
              > That said, it would be useful to have a
              > string buffer object that could be changed.[/color]

              What about StringIO?

              Comment

              • Brent W. Hughes

                #8
                Re: Why are strings immutable?

                Let me give two examples of where I think it would be nice to be able to
                change strings in place:


                First example:

                I want to add about 20,000 words to the end of a string, something like
                this:

                Str = [ ]
                for i in range(20000):
                Word = DoSomeProcessin g()
                Str += Word

                I'd actually like to say Str.extend(Word ). As it is, I'm thinking of
                something like this:

                List = [ ]
                for i in range(20000):
                Word = DoSomeProcessin g()
                List.extend(lis t(Word))
                Str = ''.join(List)


                Second example:

                I would like to reverse a string containing about 120,000 characters. I'd
                like to do it in place, but I'm planning to do something like this:

                List = list(Str)
                List.reverse()
                Str = ''.join(List)


                Comment

                • Hallvard B Furuseth

                  #9
                  Re: Why are strings immutable?

                  Brent W. Hughes wrote:
                  [color=blue]
                  > Let me give two examples of where I think it would be nice to be able to
                  > change strings in place:[/color]

                  Sure, it would be nice sometimes.
                  But immutable strings provide many nice advantages too.
                  [color=blue]
                  > I want to add about 20,000 words to the end of a string, something like
                  > this:
                  >
                  > Str = [ ]
                  > for i in range(20000):
                  > Word = DoSomeProcessin g()
                  > Str += Word
                  >
                  > I'd actually like to say Str.extend(Word ).[/color]

                  If you are doing a lot of that with the string, does it need to be a
                  single string? I've just speeded up a program significantly by changing
                  string_var = ...
                  string_var += ...
                  string_var += ...
                  ...
                  to
                  array_var = ['string']
                  array_var.appen d(...)
                  array_var.appen d(...)
                  ...
                  result = "".join(array_v ar)
                  (Well, because of how the data was structured I actually used a dict
                  which was unpacked to a list comprehension which was joined to a string,
                  but it still speeded things up.)

                  You might also speed things up with
                  append_string = array_var.appen d
                  append_string(. ..)
                  if it is too slow, since that saves a lot of attribute lookups. But
                  don't make your code more unreadable like that unless it _is_ too slow.
                  [color=blue]
                  > I would like to reverse a string containing about 120,000 characters. I'd
                  > like to do it in place, but I'm planning to do something like this:
                  >
                  > List = list(Str)
                  > List.reverse()
                  > Str = ''.join(List)[/color]

                  import array
                  a = array.array('c' , Str)
                  a.reverse()
                  Str = a.tostring()

                  Still needs two new objects, but at least that's a lot fewer than your
                  list.

                  --
                  Hallvard

                  Comment

                  • Larry Bates

                    #10
                    Re: Why are strings immutable?

                    Think about it. Since strings occupy a fixed
                    number of bytes in memory, a mutable string would
                    just be a linked list of strings. For performance
                    reasons you can't require that everything in memory
                    gets moved around when you want to add one byte to
                    a string. Multiply that by 20K and performance
                    would be terrible. Since a mutable string is just
                    a list of strings, Python just asks the programmer
                    to treat it exactly like what it REALLY is. If
                    you want to append lots of things to a string, build
                    a list and then join it into a string at the end
                    of processing.

                    Your example:

                    List = [ ]
                    for i in range(20000):
                    Word = DoSomeProcessin g()
                    List.extend(lis t(Word))
                    Str = ''.join(List)


                    will work as:

                    words=[]
                    for i in xrange(20000):
                    word = DoSomeProcessin g()
                    words.append(wo rd)

                    word_string = ' '.join(words)

                    Notes:

                    1) You build the word_list by appending words that
                    come back frmo DoSomeProcessin g().

                    2) If you want a space between your words you must
                    specify it as the character before .join() call.

                    3) range(20000) will create a list of length=20000
                    and interate over it, xrange(20000) will just create
                    an iterable object that returns the next number on
                    each sucessive call (saving both memory and the time
                    to create the 20K list).

                    4) You should stay FAR away from variables named
                    list or str (even though you capitalized the first
                    character). list and str are python functions that
                    can easily get redefined by accident. List and Str
                    will work, but I've seen MANY Python programmers walk
                    on list, str, dict by accident and later wonder why.

                    HTH,
                    Larry Bates
                    Syscon, Inc.

                    "Brent W. Hughes" <brent.hughes@c omcast.net> wrote in message
                    news:O%rWc.1712 56$8_6.61890@at tbi_s04...[color=blue]
                    > Let me give two examples of where I think it would be nice to be able to
                    > change strings in place:
                    >
                    >
                    > First example:
                    >
                    > I want to add about 20,000 words to the end of a string, something like
                    > this:
                    >
                    > Str = [ ]
                    > for i in range(20000):
                    > Word = DoSomeProcessin g()
                    > Str += Word
                    >
                    > I'd actually like to say Str.extend(Word ). As it is, I'm thinking of
                    > something like this:
                    >
                    > List = [ ]
                    > for i in range(20000):
                    > Word = DoSomeProcessin g()
                    > List.extend(lis t(Word))
                    > Str = ''.join(List)
                    >
                    >
                    > Second example:
                    >
                    > I would like to reverse a string containing about 120,000 characters. I'd
                    > like to do it in place, but I'm planning to do something like this:
                    >
                    > List = list(Str)
                    > List.reverse()
                    > Str = ''.join(List)
                    >
                    >[/color]


                    Comment

                    • Paul Rubin

                      #11
                      Re: Why are strings immutable?

                      "Larry Bates" <lbates@swamiso ft.com> writes:[color=blue]
                      > Think about it. Since strings occupy a fixed
                      > number of bytes in memory, a mutable string would
                      > just be a linked list of strings.[/color]

                      Eh? It would be treated just like Python currently treats lists.

                      In fact, array('B') does just about exactly what Brent is asking for.

                      Comment

                      • Jeff Shannon

                        #12
                        Re: Why are strings immutable?

                        Larry Bates wrote:
                        [color=blue]
                        >Your example:
                        >
                        >List = [ ]
                        >for i in range(20000):
                        > Word = DoSomeProcessin g()
                        > List.extend(lis t(Word))
                        >Str = ''.join(List)
                        >
                        >
                        >will work as:
                        >
                        >words=[]
                        >for i in xrange(20000):
                        > word = DoSomeProcessin g()
                        > words.append(wo rd)
                        >
                        >word_string = ' '.join(words)
                        >
                        >[/color]

                        Or even (using a list comp):

                        words = ' '.join( [DoSomeProcessin g() for i in xrange(20000)] )

                        Though I have to wonder what you're doing with a 20,000 word string,
                        built programmaticall y word-by-word. While I don't know what you're
                        doing, here, the way you're building it seems to suggest to me that a
                        list or dictionary may actually be a more natural way to handle your data.

                        Jeff Shannon
                        Technician/Programmer
                        Credit International

                        Comment

                        • Jeremy Bowers

                          #13
                          Re: Why are strings immutable?

                          On Mon, 23 Aug 2004 22:11:36 +0200, Hallvard B Furuseth wrote:
                          [color=blue]
                          > If you are doing a lot of that with the string, does it need to be a
                          > single string? I've just speeded up a program significantly by changing
                          > string_var = ...
                          > string_var += ...
                          > string_var += ...
                          > ...
                          > to
                          > array_var = ['string']
                          > array_var.appen d(...)
                          > array_var.appen d(...)
                          > ...
                          > result = "".join(array_v ar)
                          > (Well, because of how the data was structured I actually used a dict which
                          > was unpacked to a list comprehension which was joined to a string, but it
                          > still speeded things up.)[/color]

                          For PyDS, I contributed a class that does that and offers a += interface,
                          so it is easy to drop in without too much conversion work. It is very
                          simple.

                          In general, you should not use this and you should do it "right" the first
                          time, but for existing code this can be a convenient make-do.

                          Replace your initial "myString = ''" with "myString = StringCollector ()",
                          and depending on how you use this you may not need to change the final
                          use. Otherwise, call "str()" on your StringCollector .

                          (Note the encoding in iadd; I just added the locale call without testing
                          it, and you may want to switch it; PyDS actually uses its own system.)

                          -----------------------------

                          import locale
                          class StringCollector :

                          def __init__(self, string='', encoding = None):
                          self.buffer = StringIO()
                          if string: self += string
                          if encoding in None:
                          self.encoding = locale.getprefe rredencoding()
                          else:
                          self.encoding = encoding

                          def __iadd__(self, other):
                          if type(string) == types.UnicodeTy pe:
                          self.buffer.wri te(other.encode (self.encoding) )
                          else:
                          self.buffer.wri te(other)
                          return self

                          def __repr__(self):
                          return '<StringCollect or>'

                          def __str__(self):
                          return self.buffer.get value()

                          Comment

                          Working...