Henry Chang
Henry Chang

Reputation: 86

Python Beginner Programming

I am still working on the same encryption program before and I am currently stuck.

choice = ""
def program (str,my_fn):
    global i
    i=0
    while i<len(str):
        my_fn
        i += 1

def encrypt(my_result):
    message.append(ord(answer[i]))
while choice != "Exit":
    choice = input("Do you want to Encrypt, Decrypt,  or Exit?\n")
    if choice == "Encrypt":
        answer = input("What would you like to encrypt:\n")
        message = []
        program(answer,encrypt(message))

        print (answer)
        print (message)

So the first part of the program is simply asking the user if they wish to Encrypt, Decrypt, or Exit the program, this part works perfectly fine. However, my issue is with the functions. Function "program" is intended to serve as a repeater for the inner function for every single letter in the string. However, when I try to run the program, it continues to tell me that "i" isn't defined for the "encrypt" function and does nothing. I am certain I set "i" as a global variable so why isn't this working. In case you are wondering why I chose to make two functions, it is because I will later have to use function "program" multiple time and for this specific assignment I am required to use functions and abstractions. Thanks!

Upvotes: 0

Views: 101

Answers (2)

Blckknght
Blckknght

Reputation: 104792

The line program(answer,encrypt(message)) doesn't do what you want it to do. Rather than passing the function encrypt and its argument message to program (which can call it later), it calls the function immediately. It would pass the return value to program instead, but since encrypt(message) doesn't work without i defined, you get an exception instead.

There are a few ways you could fix this. By far the best approach is to not use global variables in your functions, and instead always pass the objects you care about as arguments or return values.

For instance, you could pass a function that encrypts a single letter to another function that repeatedly applies the first one to a string (this would be very much like the builtin map function):

def my_map(function, string):
    result = []
    for character in string:
        result.append(function(character))
    return result

def my_encryption_func(character):
    return ord(character)

If you really want to stick with your current architecture, you could make it work by using functools.partial to bind the answer argument to your encrypt function, and then call the partial object in program:

from functools import partial

def program (str,my_fn):
    global i
    i=0
    while i<len(str):
        my_fn()   # call the passed "function"
        i += 1

def encrypt(my_result):
    message.append(ord(answer[i]))

choice = ""
while choice != "Exit":
    choice = input("Do you want to Encrypt, Decrypt,  or Exit?\n")
    if choice == "Encrypt":
        answer = input("What would you like to encrypt:\n")
        message = []
        program(answer, partial(encrypt, message)) # pass a partial object here!

        print (answer)
        print (message)

Upvotes: 0

Xu Han
Xu Han

Reputation: 89

Add one line after your first line

choice = ""
i = 0

The keyword global means you declare an access to a global name. Also, using a global variable is almost never a good idea. You may want to find another way to design your function.

Upvotes: 1

Related Questions