0

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!

  • Possible duplicate of [Using global variables in a function other than the one that created them](http://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-the-one-that-created-them) – Lavaman65 Mar 11 '17 at 03:54

2 Answers2

1

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.

Xu Han
  • 89
  • 1
  • 4
0

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)
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • So sorry for not understanding this, but can you please describe further what the partial function does? Does it basically freeze part of the function? Sorry for not understanding, I looked it up on the Python site as well as other example. – Henry Chang Mar 11 '17 at 04:22
  • If you're a new programmer, don't worry about `partial` too much. It's a fairly advanced thing you don't normally need. It lets you pass some of the arguments to a function in advance without calling it yet. Later, you can call the `partial` object (perhaps with additional arguments) and only then is the original function called. My first example (which doesn't need partial or anything else complicated) is a much better design. – Blckknght Mar 11 '17 at 04:27