calling upper() on a string, not working?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Salerno

    #1

    calling upper() on a string, not working?

    Can someone tell me what's happening here. This is my code:



    PUNCT_SPACE_SET = set(string.punc tuation + string.whitespa ce)

    def filter_letters( original):
    return ''.join(set(ori ginal) - PUNCT_SPACE_SET )



    'original' is a string. The above works as expected, but when I change
    it to

    return ''.join(set(ori ginal.upper()) - PUNCT_SPACE_SET )

    it doesn't seem to work. The full code is below if it helps to understand.



    import string
    import random
    import itertools

    PUNCT_SPACE_SET = set(string.punc tuation + string.whitespa ce)

    def convert_quote(q uote):
    return encrypt_quote(q uote).split('|' )

    def encrypt_quote(o riginal):
    original_letter s = filter_letters( original)
    new_letters = list(string.asc ii_uppercase)
    while True:
    random.shuffle( new_letters)
    trans_letters = ''.join(new_let ters)[:len(original_l etters)]
    if test_code(origi nal_letters, trans_letters):
    trans_table = string.maketran s(original_lett ers, trans_letters)
    break
    return original.transl ate(trans_table )

    def filter_letters( original):
    return ''.join(set(ori ginal) - PUNCT_SPACE_SET )
    #return ''.join(set(ori ginal.upper()) - PUNCT_SPACE_SET )

    def test_code(origi nal_letters, trans_letters):
    for pair in itertools.izip( original_letter s, trans_letters):
    if pair[0] == pair[1]:
    return False
    return True

    if __name__ == '__main__':
    print convert_quote(" The past is not dead. In fact, it's not even
    past.|William Faulkner")
  • Felipe Almeida Lessa

    #2
    Re: calling upper() on a string, not working?

    Em Ter, 2006-05-16 às 20:25 +0000, John Salerno escreveu:[color=blue]
    > it doesn't seem to work. The full code is below if it helps to understand.[/color]

    Why doesn't it work? What does it do, what did you expect it to do?
    [color=blue][color=green][color=darkred]
    >>> ''.join(set('hi '))[/color][/color][/color]
    'ih'[color=blue][color=green][color=darkred]
    >>> ''.join(set('HI '))[/color][/color][/color]
    'IH'[color=blue][color=green][color=darkred]
    >>> ''.join(set('hi HI'))[/color][/color][/color]
    'ihIH'[color=blue][color=green][color=darkred]
    >>> ''.join(set('hi HI'.upper()))[/color][/color][/color]
    'IH'


    --
    Felipe.

    Comment

    • John Salerno

      #3
      Re: calling upper() on a string, not working?

      Felipe Almeida Lessa wrote:[color=blue]
      > Em Ter, 2006-05-16 às 20:25 +0000, John Salerno escreveu:[color=green]
      >> it doesn't seem to work. The full code is below if it helps to understand.[/color]
      >
      > Why doesn't it work? What does it do, what did you expect it to do?[/color]

      If you run the whole script with the first line (the one not commented),
      you get output similar to this, which is correct:
      [color=blue][color=green][color=darkred]
      >>>[/color][/color][/color]
      ["AMN RIPQ LP WOQ SNIS. BW VIDQ, LQ'P WOQ NHNW RIPQ.", 'ULJJLIY TIZJXWNE'][color=blue][color=green][color=darkred]
      >>>[/color][/color][/color]

      But if you use the line with the upper() call, you get this:
      [color=blue][color=green][color=darkred]
      >>>[/color][/color][/color]
      ["Bhe past is not dead. Dn fact, it's not even past.", 'Killiam Qaulkner'][color=blue][color=green][color=darkred]
      >>>[/color][/color][/color]

      Now, I know the actual upper() function works, but I can't understand if
      there's a problem with *when* it's being called, or what's being done
      with it to get the second result above.

      Comment

      • Michal Kwiatkowski

        #4
        Re: calling upper() on a string, not working?

        John Salerno wrote:[color=blue]
        > def encrypt_quote(o riginal):
        > original_letter s = filter_letters( original)[/color]

        You call filter_letters( ) which makes upper() on all letters, so
        original_letter s contain only uppercase letters.
        [color=blue]
        > new_letters = list(string.asc ii_uppercase)
        > while True:
        > random.shuffle( new_letters)
        > trans_letters = ''.join(new_let ters)[:len(original_l etters)]
        > if test_code(origi nal_letters, trans_letters):
        > trans_table = string.maketran s(original_lett ers,
        > trans_letters) break
        > return original.transl ate(trans_table )[/color]

        And here you're translating 'original' (which contains a lot of
        lowercase letters) with use of trans_table that maps only uppercase
        characters. This return should be:

        return original.upper( ).translate(tra ns_table)

        mk
        --
        . o . >> http://joker.linuxstuff.pl <<
        . . o It's easier to get forgiveness for being wrong
        o o o than forgiveness for being right.

        Comment

        • John Salerno

          #5
          Re: calling upper() on a string, not working?

          Michal Kwiatkowski wrote:
          [color=blue]
          > And here you're translating 'original' (which contains a lot of
          > lowercase letters) with use of trans_table that maps only uppercase
          > characters. This return should be:
          >
          > return original.upper( ).translate(tra ns_table)[/color]

          Thank you!!! :)

          Comment

          • Larry Bates

            #6
            Re: calling upper() on a string, not working?

            John Salerno wrote:[color=blue]
            > Can someone tell me what's happening here. This is my code:
            >
            >
            >
            > PUNCT_SPACE_SET = set(string.punc tuation + string.whitespa ce)
            >
            > def filter_letters( original):
            > return ''.join(set(ori ginal) - PUNCT_SPACE_SET )
            >
            >
            >
            > 'original' is a string. The above works as expected, but when I change
            > it to
            >
            > return ''.join(set(ori ginal.upper()) - PUNCT_SPACE_SET )
            >
            > it doesn't seem to work. The full code is below if it helps to understand.
            >
            >
            >
            > import string
            > import random
            > import itertools
            >
            > PUNCT_SPACE_SET = set(string.punc tuation + string.whitespa ce)
            >
            > def convert_quote(q uote):
            > return encrypt_quote(q uote).split('|' )
            >
            > def encrypt_quote(o riginal):
            > original_letter s = filter_letters( original)
            > new_letters = list(string.asc ii_uppercase)
            > while True:
            > random.shuffle( new_letters)
            > trans_letters = ''.join(new_let ters)[:len(original_l etters)]
            > if test_code(origi nal_letters, trans_letters):
            > trans_table = string.maketran s(original_lett ers, trans_letters)
            > break
            > return original.transl ate(trans_table )
            >
            > def filter_letters( original):
            > return ''.join(set(ori ginal) - PUNCT_SPACE_SET )
            > #return ''.join(set(ori ginal.upper()) - PUNCT_SPACE_SET )
            >
            > def test_code(origi nal_letters, trans_letters):
            > for pair in itertools.izip( original_letter s, trans_letters):
            > if pair[0] == pair[1]:
            > return False
            > return True
            >
            > if __name__ == '__main__':
            > print convert_quote(" The past is not dead. In fact, it's not even
            > past.|William Faulkner")[/color]

            Not exactly sure why you think its not working. When you create a set
            from the original.upper( ) you get a smaller number of characters because
            you no longer get both 'T' and 't' as well as 'I' and 'i' as you do in
            the lower case version of the string.
            [color=blue][color=green][color=darkred]
            >>> set(original.sp lit('|')[0])[/color][/color][/color]
            set(['a', ' ', 'c', 'e', 'd', "'", 'f', 'i', 'h', ',', 'o', 'n', 'p', 's', 'T',
            'v', 'I', '.', 't'])[color=blue][color=green][color=darkred]
            >>> set(original.sp lit('|')[0].upper())[/color][/color][/color]
            set(['A', ' ', 'C', 'E', 'D', "'", 'F', 'I', 'H', ',', 'O', 'N', 'P', 'S', 'T',
            'V', '.'])[color=blue][color=green][color=darkred]
            >>>[/color][/color][/color]

            sets can only contain "unique" entries. Letters that are repeated only get
            added once. When you do .upper() you convert lowercase 't' to 'T' and lower
            case 'i' to 'I' so that letter only gets added to the set a single time.

            Hope info helps.

            Larry Bates

            Comment

            • Bruno Desthuilliers

              #7
              Re: calling upper() on a string, not working?

              John Salerno a écrit :[color=blue]
              > Can someone tell me what's happening here. This is my code:
              >
              > PUNCT_SPACE_SET = set(string.punc tuation + string.whitespa ce)
              >
              > def filter_letters( original):
              > return ''.join(set(ori ginal) - PUNCT_SPACE_SET )
              >
              > 'original' is a string. The above works as expected, but when I change
              > it to
              >
              > return ''.join(set(ori ginal.upper()) - PUNCT_SPACE_SET )
              >
              > it doesn't seem to work. The full code is below if it helps to understand.
              >[/color]

              Don't assume str.upper() is broken !-)

              In fact, your problem is that you create the translation table based on
              uppercase letters, and apply it to a non uppercased string :
              [color=blue]
              > import string
              > import random
              > import itertools
              >
              > PUNCT_SPACE_SET = set(string.punc tuation + string.whitespa ce)
              >
              > def convert_quote(q uote):
              > return encrypt_quote(q uote).split('|' )
              >
              > def encrypt_quote(o riginal):[/color]
              # Since it's here that we define that the new letters
              # will be uppercase only, it's our responsability
              # to handle any related conditions and problems
              # The other functions shouldn't have to even know this.
              original = original.upper( )[color=blue]
              > original_letter s = filter_letters( original)
              > new_letters = list(string.asc ii_uppercase)
              > while True:
              > random.shuffle( new_letters)
              > trans_letters = ''.join(new_let ters)[:len(original_l etters)]
              > if test_code(origi nal_letters, trans_letters):
              > trans_table = string.maketran s(original_lett ers, trans_letters)
              > break
              > return original.transl ate(trans_table )
              >
              > def filter_letters( original):[/color]
              # here, we *dont* have to do anything else than filtering
              # upper/lower case is *not* our problem.[color=blue]
              > return ''.join(set(ori ginal) - PUNCT_SPACE_SET )
              >
              > def test_code(origi nal_letters, trans_letters):
              > for pair in itertools.izip( original_letter s, trans_letters):
              > if pair[0] == pair[1]:
              > return False
              > return True
              >
              > if __name__ == '__main__':
              > print convert_quote(" The past is not dead. In fact, it's not even
              > past.|William Faulkner")[/color]

              ["XCD ONKX AK IGX LDNL. AI WNBX, AX'K IGX DYDI ONKX.", 'UAEEANP WNREQIDS']

              Comment

              • John Salerno

                #8
                Re: calling upper() on a string, not working?

                Bruno Desthuilliers wrote:
                [color=blue][color=green]
                >> def encrypt_quote(o riginal):[/color]
                > # Since it's here that we define that the new letters
                > # will be uppercase only, it's our responsability
                > # to handle any related conditions and problems
                > # The other functions shouldn't have to even know this.
                > original = original.upper( )[/color]
                [color=blue][color=green]
                >> def filter_letters( original):[/color]
                > # here, we *dont* have to do anything else than filtering
                > # upper/lower case is *not* our problem.[color=green]
                >> return ''.join(set(ori ginal) - PUNCT_SPACE_SET )[/color][/color]

                Thanks, I was wondering if it only needed to be done in a single place
                like that.

                Comment

                • Scott David Daniels

                  #9
                  Re: calling upper() on a string, not working?

                  John Salerno wrote:
                  <Some code, with a request to get case working.>
                  Others have shown you where the bug was.

                  You might want to change encrypt_quote like this:

                  XXX> def encrypt_quote(o riginal):
                  def encrypt_quote(o riginal, casemap=True):
                  XXX> original_letter s = filter_letters( original)
                  if casemap:
                  original_letter s = filter_letters( original.upper( ))
                  else:
                  original_letter s = filter_letters( original)
                  XXX> new_letters = list(string.asc ii_uppercase)
                  if len(original_le tters) > 26:
                  new_letters = list(string.asc ii_uppercase +
                  string.ascii_lo wercase)
                  casemap = False
                  else:
                  new_letters = list(string.asc ii_uppercase)[color=blue]
                  > while True:
                  > random.shuffle( new_letters)
                  > trans_letters = ''.join(new_let ters)[:len(original_l etters)]
                  > if test_code(origi nal_letters, trans_letters):[/color]
                  XXX> trans_table = string.maketran s(original_lett ers,
                  trans_letters)
                  if casemap:
                  trans_table = string.maketran s(
                  original_letter s + original_letter s.lower(),
                  trans_letters + trans_letters.l ower())
                  else:
                  trans_table = string.maketran s(original_lett ers,
                  trans_letters)[color=blue]
                  > break
                  > return original.transl ate(trans_table )[/color]


                  --Scott David Daniels
                  scott.daniels@a cm.org

                  Comment

                  • Paul Rubin

                    #10
                    Re: calling upper() on a string, not working?

                    John Salerno <johnjsal@NOSPA Mgmail.com> writes:[color=blue]
                    > Now, I know the actual upper() function works, but I can't understand
                    > if there's a problem with *when* it's being called, or what's being
                    > done with it to get the second result above.[/color]

                    You are translating "original" which still has lower case letters:

                    return original.transl ate(trans_table )

                    You want:

                    return original.upper( ).translate(tra ns_table)

                    Comment

                    • Bruno Desthuilliers

                      #11
                      Re: calling upper() on a string, not working?

                      John Salerno a écrit :[color=blue]
                      > Bruno Desthuilliers wrote:
                      >[color=green][color=darkred]
                      >>> def encrypt_quote(o riginal):[/color]
                      >>
                      >> # Since it's here that we define that the new letters
                      >> # will be uppercase only, it's our responsability
                      >> # to handle any related conditions and problems
                      >> # The other functions shouldn't have to even know this.
                      >> original = original.upper( )[/color]
                      >
                      >[color=green][color=darkred]
                      >>> def filter_letters( original):[/color]
                      >>
                      >> # here, we *dont* have to do anything else than filtering
                      >> # upper/lower case is *not* our problem.
                      >>[color=darkred]
                      >>> return ''.join(set(ori ginal) - PUNCT_SPACE_SET )[/color][/color]
                      >
                      >
                      > Thanks, I was wondering if it only needed to be done in a single place
                      > like that.[/color]

                      It's always better to do something in a single place - you may here of
                      this as the DRY (Dont Repeat Yourself) or SPOT (Single Point Of
                      Transformation) rule.

                      The way you wrote it, part of encrypt_quote's responsability and
                      knowldege was leaking into filter_letters. This is a Bad Thing(tm), and
                      should be avoided by any mean.

                      Comment

                      Working...