That guy Who is good
That guy Who is good

Reputation: 11

Python: Variable keeping value after restart

I am creating a basic Caesar Cypher in python and I have finished the main part of it (the cypher part) but as I have been testing the code I have found that my shift variable is keeping the same value when I use a function to restart the code, I have tried resetting all the variables but it has not changed the outcome, here is the code:

import sys
accept_yes = ["Yes", "yes", "Y", "y"]
accept_no = ["No", "no", "N", "n"]
accept_encrypt = ["Encrypt", "encrypt", "E", "e"]
accept_decrypt = ["Decrypt", "decrypt", "D", "d"]
accept_exit = ["Exit", "exit"]
norm_alph = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
crypt_alph = [""]

def Intro():
    encrypt_or_decrypt = input("Do you want to encrypt, decrypt or exit?: ") 
    if encrypt_or_decrypt in accept_encrypt:
        print("You chose encrypt")
        print("Enter a message to encrypt:  ") #Asks user for msg to encrypt
        Encrypt()
    elif encrypt_or_decrypt in accept_decrypt:
        print("You chose decrypt")
        print("Enter a message to decrypt:  ") #Asks user for msg to decrypt
        Decrypt()
    elif encrypt_or_decrypt in accept_exit:
        print ("Exiting...")
        sys.exit()
    else:
        print("Invalid Input")
        print("Please try again")
        Intro()

def Encrypt():
    en_or_de = ("")
    msg = input("").lower()
    crypt_msg = ("")
    shift = int(input("Enter a number to offset by\n"))
    shift = shift + 1
    for en_or_de in range(0,26):
        crypt_alph.append(norm_alph[(en_or_de+shift)%26])
    for en_or_de in msg:
        if norm_alph.count(en_or_de):
            crypt_msg += crypt_alph[norm_alph.index(en_or_de.lower())]
        else:
          crypt_msg += en_or_de
    print (crypt_msg.upper())
    Intro()

def Decrypt():
    en_or_de = ("")
    msg = input("").lower()
    crypt_msg = ("")
    shift = ("")
    shift = int(input("Enter a number to offset by\n"))
    shift = shift - 1
    for en_or_de in range(0,26):
        crypt_alph.append(norm_alph[(en_or_de-shift)%26])
    for en_or_de in msg:
      if norm_alph.count(en_or_de):
        crypt_msg += crypt_alph[norm_alph.index(en_or_de.lower())]
      else:
        crypt_msg += en_or_de
    print (crypt_msg.upper())
    Intro()

Intro()

I really hope someone can help me because I have been stuck with this problem for a while.

Thank you in advance!

Upvotes: 0

Views: 2221

Answers (1)

Stephen Jackson
Stephen Jackson

Reputation: 59

Your issue is that the crypt_alph list is getting set by the first time you call your function, and then each subsequent time the Encrypt() function is called, the new crypt_alph contents are getting appended to the crypt_alph from the first call.

I've added a line to print crypt_alph so you can see what's happening:

Do you want to encrypt, decrypt or exit?: e
You chose encrypt
Enter a message to encrypt:  
Hello World
Enter a number to offset by
3
crypt_alph: ['', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c']
JGNNQ YQTNF
Do you want to encrypt, decrypt or exit?: e
You chose encrypt
Enter a message to encrypt:  
Hello World
Enter a number to offset by
4
crypt_alph: ['', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd']
JGNNQ YQTNF
Do you want to encrypt, decrypt or exit?: exit
Exiting...

See how the second time crypt_alph is printed it is way long?

The short explanation of why this happens is that global lists in python can be changed with actions like append(). To fix your issue, you should move crypt_alph into your function, like this:

def Encrypt():
    crypt_alph = [""]
    en_or_de = ("")
    msg = input("").lower()
    crypt_msg = ("")
    shift = int(input("Enter a number to offset by\n"))
    shift = shift + 1
    for en_or_de in range(0,26):
        crypt_alph.append(norm_alph[(en_or_de+shift)%26])
    for en_or_de in msg:
        if norm_alph.count(en_or_de):
            crypt_msg += crypt_alph[norm_alph.index(en_or_de.lower())]
        else:
          crypt_msg += en_or_de
    print (crypt_msg.upper())
    Intro()

It's a tricky little feature of globals in python. In general, it is a good idea to avoid globals!

Upvotes: 1

Related Questions