Python: Caesar Cipher functions

Hi, I’m running into an error when trying to create a function that loops through an encrypted message and uses a key to decipher it (Caesar Cipher method).

However, I keep getting this error:

Traceback (most recent call last):
File “script.py”, line 19, in
print(crack_message(encrypted_message, key))
File “script.py”, line 13, in crack_message
decrypted_message += new_char
UnboundLocalError: local variable ‘decrypted_message’ referenced before assignment

Here is the code I’m working on:

#Decrpyt Message:
letters = “abcdefghijklmnopqrstuvwxyz”
encrypted_message = “xuo jxuhu! jxyi yi qd unqcfbu ev q squiqh syfxuh. muhu oek qrbu je tusetu yj? y xefu ie! iudt cu q cuiiqwu rqsa myjx jxu iqcu evviuj!”
key= int(10)
decrypted_message=“”

def crack_message(encrypted_message, key):
for ch in encrypted_message:
if ch in letters:
position = letters.find(ch)
new_pos = (position + key) % 26
new_char = letters[new_pos]
decrypted_message += new_char
return decrypted_message
else:
decrypted_message += ch
return decrypted_message

print(crack_message(encrypted_message, key))

What am I missing here? Thanks in advance!

decrypted_message is probable out of scope. (Hard to say because without formatting, this code can be doing different things).

But simply put, you try to do an operation on decrypted_message but it’s not a variable that exists yet in the scope of the operation.

2 Likes

You have two errors, the first you’ll find after this one. The second is slight guess work without proper indents. Python really needs structure to make sense.

# don't like this one out here, but ok
letters = "abcdefghijklmnopqrstuvwxyz"

encrypted_message = "xuo jxuhu! jxyi yi qd unqcfbu ev q squiqh syfxuh. muhu oek qrbu je tusetu yj? y xefu ie! iudt cu q cuiiqwu rqsa myjx jxu iqcu evviuj!"
key = int(10) # the int is redundant, btw

# !!! error, this shouldn't be here
# decrypted_message=""

def crack_message(encrypted_message, key):
    # this is your return value, you want it here
    # you also want it set to "" every time you call the function
    decrypted_message=""

    for ch in encrypted_message:
        if ch in letters:
            position = letters.find(ch)
            new_pos = (position + key) % 26
            new_char = letters[new_pos]
            decrypted_message += new_char
            # error two, this return shouldn't be here at all
            # return decrypted_message
        else:
            decrypted_message += ch
    return decrypted_message

print(crack_message(encrypted_message, key))

Hi @baavgai ! Thanks for your help.
This worked exactly as I intended.

Still a little confused as to why the decrypted_message=“” outside of the function caused an error when having the key, letters and encrypted_message outside of it did NOT. But, I am still fairly new to this so I’m sure I can read back on the topic and find some in-depth answer there.

In the meantime, thanks again!

Hi @toastedpitabread ,

Thanks for your help!

Yes, it was indeed giving an out of scope error, though I’m a bit confused as to why.

However, baavgai’s code notes below worked and it all works smoothly now.

Thanks again!

Well, key and encrypted_message are not outside, they’re inside: you passed them: def crack_message(encrypted_message, key):. Indeed, if you had a key lurking about in a higher scope, the one you passed would block it.

The letters is trickier. Globals are available, or not, depending on when the function is asking for them and what it’s doing with them.

Here a simple example:

key = 13 # declared globally

def foo():
    # uses a variable name outside function scope
    # in this case, a global
    print("foo key =", key) 

def bar(key):
    # uses the passed variable
    print("bar key =", key)

def baz():
    # uses global
    print("baz key 1 =", key)
    key = 91 # sets global to different value
    print("baz key 2 =", key)

foo()
bar(42)
baz()

Results:

foo key = 13
bar key = 42
Traceback (most recent call last):
  File "t.py", line 20, in <module>
    baz()
  File "t.py", line 14, in baz
    print("baz key 1 =", key)
                         ^^^
UnboundLocalError: cannot access local variable 'key' where it is not associated with a value

That assignment is what makes python cranky. The minute you try to assign, that global becomes a local and confusion follows.

If you explicitly declare it a global, it will work:

key = 13

def baz():
    global key
    print("baz key 1 =", key)
    key = 91
    print("baz key 2 =", key)

baz()

While double checking that global syntax, I found a write up that did a better job than I did, here.

1 Like

Thanks! That page is very helpful and does a great job at explaining it!