0
sequence = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'


def caesar( original, variationShift):
    '''returns: a version of original created by replacing each letter with 
       the letter "variationShift" units later in the alphabet sequence.
       If variationShift is negative, replacing letter is found earlier in  
       alphabet.'''
    index = 0
    result = ''
    while index < len( original):
        lookFor = original[ index]
        foundAt = sequence.find( lookFor)
        if foundAt == -1:
            # untranslatable character
            result += lookFor
        else:
            result += sequence[ variationShift]  # negative indexes OK!

        index += 1
    return result

def encryptCaesar (original):
    caesar( original, foundAt - 3)
    return result

def decryptCaesar (original):
    caesar( original, (foundAt + 3) % len(sequence))
    return result

The variable foundAt is constantly being said to be undefined. Yet, it is defined in caesar. Is a variable undefined until the function is actually run once? Or during that run?

3
  • foundAt is a local variable within the caesar function. It's not visible outside the function. Commented Apr 30, 2014 at 3:56
  • foundAt is only defined within the scope of caesar. It's not considered to exist anywhere else. So, the question is, do you really need to use foundAt in those other methods? It wouldn't make sense to me that a cipher needs to know that much at that level. Commented Apr 30, 2014 at 3:56
  • And even if there weren't a scope problem, you're using the variable in the argument to caesar, so you need it to have a value before it's set inside the function. What sense does that make? Commented Apr 30, 2014 at 3:59

3 Answers 3

2

The other answers explain about variable scope, but you have some more basic issues. You are mixing where these variables are used. What you want to do is pass the shift. You don't know the foundAt location at the calling point, that is calculated in the loop. The other issue is the return value. You need to return the value from caesar(). The code below does the standard caesar encryption and decryption.

sequence = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

def caesar( original, variationShift):
    '''returns: a version of original created by replacing each letter with 
       the letter "variationShift" units later in the alphabet sequence.
       If variationShift is negative, replacing letter is found earlier in  
       alphabet.'''
    index = 0
    result = ''
    while index < len( original):
        lookFor = original[ index]
        foundAt = sequence.find( lookFor)
        if foundAt == -1:
            # untranslatable character
            result += lookFor
        else:
            result += sequence[ (foundAt + variationShift) % len(sequence)]
        index += 1
    return result

def encryptCaesar (original):
    return caesar( original, -3)

def decryptCaesar (original):
    return caesar( original, 3)
Sign up to request clarification or add additional context in comments.

Comments

0

None of the code inside the function definition is actually run until the function is executed.

Furthermore, variables defined inside a function are only valid inside that function. To quote A Guide to Python namespaces:

At any time there are a number of scopes in operation: the scope of the current function you’re in, the scope of the module and then the scope of the Python builtins. This nesting of scopes means that one function can’t access names inside another function.

foundAt is an example of a variable defined inside a function namespace (the namespace of caesar). sequence is an example of a variable defined inside the module namespace. So, you can access sequence inside caesar and other functions, but you cannot access foundAt outside of caesar.

If you want foundAt to be accessible inside encryptCaesar you need to pass it in as an argument, or declare it in a namespace that is a parent of encryptCaesar (the module namespace -- or, alternatively, you can define encryptCaesar inside caesar and access the variable defined in the parent function via a closure). In most cases passing it in as an argument is what you wnat.

Comments

0

Due to the scope of the function, foundAt is a local variable only found within the caesar function. To get around that, use global variables:

>>> def foo():
...     global oof
...     oof = 9
... 
>>> oof
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'oof' is not defined
>>> def boo():
...     global oof
...     oof+=1
... 
>>> global oof
>>> foo()
>>> oof
9
>>> boo()
>>> oof
10
>>> 

In your code:

sequence = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'


def caesar( original, variationShift):
    global foundAt
    '''returns: a version of original created by replacing each letter with 
       the letter "variationShift" units later in the alphabet sequence.
       If variationShift is negative, replacing letter is found earlier in  
       alphabet.'''
    index = 0
    result = ''
    while index < len( original):
        lookFor = original[ index]
        foundAt = sequence.find( lookFor)
        if foundAt == -1:
            # untranslatable character
            result += lookFor
        else:
            result += sequence[ variationShift]  # negative indexes OK!

        index += 1
    return result

def encryptCaesar (original):
    global foundAt
    caesar( original, foundAt - 3)
    return result

def decryptCaesar (original):
    global foundAt
    caesar( original, (foundAt + 3) % len(sequence))
    return result

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.