calling upper() on a string, not working?

Discussion in 'Python' started by John Salerno, May 16, 2006.

  1. John Salerno

    John Salerno Guest

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



    PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)

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



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

    return ''.join(set(original.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.punctuation + string.whitespace)

    def convert_quote(quote):
    return encrypt_quote(quote).split('|')

    def encrypt_quote(original):
    original_letters = filter_letters(original)
    new_letters = list(string.ascii_uppercase)
    while True:
    random.shuffle(new_letters)
    trans_letters = ''.join(new_letters)[:len(original_letters)]
    if test_code(original_letters, trans_letters):
    trans_table = string.maketrans(original_letters, trans_letters)
    break
    return original.translate(trans_table)

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

    def test_code(original_letters, trans_letters):
    for pair in itertools.izip(original_letters, 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")
     
    John Salerno, May 16, 2006
    #1
    1. Advertising

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


    Why doesn't it work? What does it do, what did you expect it to do?

    >>> ''.join(set('hi'))

    'ih'
    >>> ''.join(set('HI'))

    'IH'
    >>> ''.join(set('hiHI'))

    'ihIH'
    >>> ''.join(set('hiHI'.upper()))

    'IH'


    --
    Felipe.
     
    Felipe Almeida Lessa, May 16, 2006
    #2
    1. Advertising

  3. John Salerno

    John Salerno Guest

    Felipe Almeida Lessa wrote:
    > Em Ter, 2006-05-16 às 20:25 +0000, John Salerno escreveu:
    >> it doesn't seem to work. The full code is below if it helps to understand.

    >
    > Why doesn't it work? What does it do, what did you expect it to do?


    If you run the whole script with the first line (the one not commented),
    you get output similar to this, which is correct:

    >>>

    ["AMN RIPQ LP WOQ SNIS. BW VIDQ, LQ'P WOQ NHNW RIPQ.", 'ULJJLIY TIZJXWNE']
    >>>


    But if you use the line with the upper() call, you get this:

    >>>

    ["Bhe past is not dead. Dn fact, it's not even past.", 'Killiam Qaulkner']
    >>>


    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.
     
    John Salerno, May 16, 2006
    #3
  4. John Salerno wrote:
    > def encrypt_quote(original):
    > original_letters = filter_letters(original)


    You call filter_letters() which makes upper() on all letters, so
    original_letters contain only uppercase letters.

    > new_letters = list(string.ascii_uppercase)
    > while True:
    > random.shuffle(new_letters)
    > trans_letters = ''.join(new_letters)[:len(original_letters)]
    > if test_code(original_letters, trans_letters):
    > trans_table = string.maketrans(original_letters,
    > trans_letters) break
    > return original.translate(trans_table)


    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(trans_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.
     
    Michal Kwiatkowski, May 16, 2006
    #4
  5. John Salerno

    John Salerno Guest

    Michal Kwiatkowski wrote:

    > 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(trans_table)


    Thank you!!! :)
     
    John Salerno, May 16, 2006
    #5
  6. John Salerno

    Larry Bates Guest

    John Salerno wrote:
    > Can someone tell me what's happening here. This is my code:
    >
    >
    >
    > PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
    >
    > def filter_letters(original):
    > return ''.join(set(original) - PUNCT_SPACE_SET)
    >
    >
    >
    > 'original' is a string. The above works as expected, but when I change
    > it to
    >
    > return ''.join(set(original.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.punctuation + string.whitespace)
    >
    > def convert_quote(quote):
    > return encrypt_quote(quote).split('|')
    >
    > def encrypt_quote(original):
    > original_letters = filter_letters(original)
    > new_letters = list(string.ascii_uppercase)
    > while True:
    > random.shuffle(new_letters)
    > trans_letters = ''.join(new_letters)[:len(original_letters)]
    > if test_code(original_letters, trans_letters):
    > trans_table = string.maketrans(original_letters, trans_letters)
    > break
    > return original.translate(trans_table)
    >
    > def filter_letters(original):
    > return ''.join(set(original) - PUNCT_SPACE_SET)
    > #return ''.join(set(original.upper()) - PUNCT_SPACE_SET)
    >
    > def test_code(original_letters, trans_letters):
    > for pair in itertools.izip(original_letters, 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")


    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.

    >>> set(original.split('|')[0])

    set(['a', ' ', 'c', 'e', 'd', "'", 'f', 'i', 'h', ',', 'o', 'n', 'p', 's', 'T',
    'v', 'I', '.', 't'])
    >>> set(original.split('|')[0].upper())

    set(['A', ' ', 'C', 'E', 'D', "'", 'F', 'I', 'H', ',', 'O', 'N', 'P', 'S', 'T',
    'V', '.'])
    >>>


    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
     
    Larry Bates, May 16, 2006
    #6
  7. John Salerno

    John Salerno Guest

    Bruno Desthuilliers wrote:

    >> def encrypt_quote(original):

    > # 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()


    >> def filter_letters(original):

    > # here, we *dont* have to do anything else than filtering
    > # upper/lower case is *not* our problem.
    >> return ''.join(set(original) - PUNCT_SPACE_SET)


    Thanks, I was wondering if it only needed to be done in a single place
    like that.
     
    John Salerno, May 16, 2006
    #7
  8. 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(original):
    def encrypt_quote(original, casemap=True):
    XXX> original_letters = filter_letters(original)
    if casemap:
    original_letters = filter_letters(original.upper())
    else:
    original_letters = filter_letters(original)
    XXX> new_letters = list(string.ascii_uppercase)
    if len(original_letters) > 26:
    new_letters = list(string.ascii_uppercase +
    string.ascii_lowercase)
    casemap = False
    else:
    new_letters = list(string.ascii_uppercase)
    > while True:
    > random.shuffle(new_letters)
    > trans_letters = ''.join(new_letters)[:len(original_letters)]
    > if test_code(original_letters, trans_letters):

    XXX> trans_table = string.maketrans(original_letters,
    trans_letters)
    if casemap:
    trans_table = string.maketrans(
    original_letters + original_letters.lower(),
    trans_letters + trans_letters.lower())
    else:
    trans_table = string.maketrans(original_letters,
    trans_letters)
    > break
    > return original.translate(trans_table)



    --Scott David Daniels
     
    Scott David Daniels, May 17, 2006
    #8
  9. John Salerno a écrit :
    > Can someone tell me what's happening here. This is my code:
    >
    > PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
    >
    > def filter_letters(original):
    > return ''.join(set(original) - PUNCT_SPACE_SET)
    >
    > 'original' is a string. The above works as expected, but when I change
    > it to
    >
    > return ''.join(set(original.upper()) - PUNCT_SPACE_SET)
    >
    > it doesn't seem to work. The full code is below if it helps to understand.
    >


    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 :

    > import string
    > import random
    > import itertools
    >
    > PUNCT_SPACE_SET = set(string.punctuation + string.whitespace)
    >
    > def convert_quote(quote):
    > return encrypt_quote(quote).split('|')
    >
    > def encrypt_quote(original):

    # 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()
    > original_letters = filter_letters(original)
    > new_letters = list(string.ascii_uppercase)
    > while True:
    > random.shuffle(new_letters)
    > trans_letters = ''.join(new_letters)[:len(original_letters)]
    > if test_code(original_letters, trans_letters):
    > trans_table = string.maketrans(original_letters, trans_letters)
    > break
    > return original.translate(trans_table)
    >
    > def filter_letters(original):

    # here, we *dont* have to do anything else than filtering
    # upper/lower case is *not* our problem.
    > return ''.join(set(original) - PUNCT_SPACE_SET)
    >
    > def test_code(original_letters, trans_letters):
    > for pair in itertools.izip(original_letters, 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")


    ["XCD ONKX AK IGX LDNL. AI WNBX, AX'K IGX DYDI ONKX.", 'UAEEANP WNREQIDS']
     
    Bruno Desthuilliers, May 17, 2006
    #9
  10. John Salerno

    Paul Rubin Guest

    John Salerno <> writes:
    > 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.


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

    return original.translate(trans_table)

    You want:

    return original.upper().translate(trans_table)
     
    Paul Rubin, May 17, 2006
    #10
  11. John Salerno a écrit :
    > Bruno Desthuilliers wrote:
    >
    >>> def encrypt_quote(original):

    >>
    >> # 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()

    >
    >
    >>> def filter_letters(original):

    >>
    >> # here, we *dont* have to do anything else than filtering
    >> # upper/lower case is *not* our problem.
    >>
    >>> return ''.join(set(original) - PUNCT_SPACE_SET)

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


    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.
     
    Bruno Desthuilliers, May 17, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Brad Smith
    Replies:
    2
    Views:
    482
    Blaise Pascal Tine
    Jun 27, 2003
  2. John F Dutcher
    Replies:
    2
    Views:
    336
    Duncan Booth
    Dec 4, 2003
  3. Steven D'Aprano
    Replies:
    4
    Views:
    315
    Terry Reedy
    May 24, 2010
  4. James Mills
    Replies:
    2
    Views:
    366
    geremy condra
    Jun 10, 2010
  5. BlackHelicopter
    Replies:
    0
    Views:
    527
    BlackHelicopter
    Jan 31, 2013
Loading...

Share This Page