Reputation: 206
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?
Upvotes: 0
Views: 1166
Reputation: 1785
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)
Upvotes: 2
Reputation: 19264
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
>>>
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
Upvotes: 0
Reputation: 19963
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.
Upvotes: 0