Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I'm new to python, and programming in general. I'm also a crypto nerd. I wrote this program to do a simple caesar shift by a user inputted key, and then deshift. I'm really enjoying it, but I've run out of ideas on improvements! Can you think of anything?

def decrypt():
    a=raw_input("Give me the word to decrypt:")
    number=input("What was it shifted by?")
    b=list(a)
    str(b)
    c=[ord(x)for x in(b)]
    d=[]
    for i in c:
        d.append(i-number)
    e=[chr(i) for i in (d)]
    e="".join(e)
    print "Decryption Successful, your word is",e,"!"

def encrypt():
    a=raw_input("Give me a word:")
    number=input("Give me a number:")
    b=list(a)
    str(b)
    c=[ord(x)for x in(b)]
    d=[]
    for i in c:
        d.append(i+number)
    e=[chr(i) for i in (d)]
    e="".join(e)
    print "Your Caesar shifted result (ascii code) is:",e,"!"
    print "Your key is", number, ",remember that!"

def menu():    
    print "\n\n\nWelcome to the Caesar Shifter."
    print "What would you like to do?"
    print "Option 1:Encrypt Word"
    print "Option 2:Decrypt Word"
    print "If you would like to quit, press 0."
    choice=input("Pick your selection:")
    if choice==1:
        run=encrypt()
        run
        menu()
    elif choice==2:
        derun=decrypt()
        derun
        menu()
    elif choice==0:
        quit
    else:
        print"That is not a correct selection, please pick either 1, or 2."

menu()

This is also my first post, so any etiquette I violated, tell me! I'd like to become a part of this community, hopefully be the one answering some questions...eventually. :P

share|improve this question
4  
you might be better off posting this to codeview stackexchange, otherwise +1 for the attitude – Uku Loskit Jun 29 '11 at 18:18
Agree with previous comment. One "easy way" to often improve code is to use more (smaller) functions that do less but do whatever they do really well -- it makes the program more modular, testable, and the function names (if chosen correctly) add self-documentation. – pst Jun 29 '11 at 18:23
So I should break up my functions more? So when say "encrypt" is run it calls 2 sub functions as opposed to just running that chunk of code? – SecNewbie Jun 29 '11 at 18:30

migrated from stackoverflow.com Jun 29 '11 at 20:28

3 Answers

up vote 6 down vote accepted

This might not be quite what you've got in mind, but one big improvement you could make would be to use meaningful variable names and insert whitespace.

def decrypt():
    cyphertext = raw_input('Give me the word to decrypt:')
    shift = input('What was it shifted by?')

    cypher_chars = list(cyphertext)
    str(b) # this does nothing; you should remove it
    cypher_ords = [ord(x) for x in cypher_list]
    plaintext_ords = []
    for i in cypher_ords:
        plaintext_ords.append(i - shift)

    plaintext_chars = [chr(i) for i in plaintext_ords]
    plaintext = ''.join(plaintext_chars)
    print 'Decryption Successful, your word is', plaintext, '!'

Of course you could actually compress much of this into a one-liner. But for a new programmer, I'd suggest sticking with readable variable names that make it clear what's going on.

Still, you could do that while compressing the code a bit:

def decrypt():
    cyphertext = raw_input('Give me the word to decrypt:')
    shift = input('What was it shifted by?')

    cypher_ords = [ord(x) for x in cyphertext]
    plaintext_ords = [o - shift for o in cypher_ords]
    plaintext_chars = [chr(i) for i in plaintext_ords]
    plaintext = ''.join(plaintext_chars)
    print 'Decryption Successful, your word is', plaintext, '!'
share|improve this answer
Ok thanks, is it more a style system change so it's more interpretable? – SecNewbie Jun 29 '11 at 18:31
@SecNewbie, yes, exactly. Using variable names like a, b, etc is ok if you're planning to throw those variables away immediately or on the next line. But it's much easier for others to read your code if you give descriptive names to variables that are used throughout the function. For that matter, it's much easier for you to read your code, after setting it aside and returning to it after six months! – senderle Jun 29 '11 at 18:40
def decrypt():
    cyphertext = raw_input("Give me the word to decrypt:")
    shift = input("What was it shifted by?")
    answer = "".join([chr(ord(char)-shift) for char in cyphertext])
    print "Decryption Successful, your word is %s!" %answer

def encrypt():
    cleartext = raw_input("Give me a word:")
    shift = input("Give me a number:")
    answer = "".join([chr(ord(char)+shift) for char in cyphertext])
    print "Your Caesar shifted result (ascii code) is %s!" %answer
    print "Your key is %d,remember that!" %shift
share|improve this answer
I understand that it condenses the code a lot, but what do the '%' symbols do? – SecNewbie Jun 29 '11 at 18:32
1  
@SecNewbie, the % symbol is the Python string formatting operator. @inspectorG4dget, note that it's slightly cleaner and more efficient to join on a generator expression rather than a list comprehension (just remove the square brackets), because it doesn't build a list only to throw it away. – benhoyt Jun 29 '11 at 18:40
They are for "pretty printing". Essentially, %s is a placeholder for a string, %d for int, %f for float, etc – inspectorG4dget Jun 29 '11 at 18:41
Ahh got it. Thanks for the help. Off topic: Why was I marked down/closed? – SecNewbie Jun 29 '11 at 18:43
See, did not know that that existed. :P. I dont think people entirely read the bottom of my post before they down voted. Will post there in the future. Thanks! – SecNewbie Jun 29 '11 at 18:49

I have to recommend against use of input. Input allows the user to enter arbitrary python expressions which is not what you want. Instead use int(raw_input()) to get a number from the user.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.