Error message saying variable not defined when it is. Python - python

I am trying to create a simple encryption program in python using functions but am having a problem where I get an error message when I run the program saying ('msgReversed' is not defined) when it is.
the program works by first reversing the users message and then shifting the letters to the value of the Key
alphabet=("abcdefghijklmnopqrstuvwxyz ")
def userInput():
plaintext=input("Enter message to encript")
k=int(input("Enter encription Key you want to use (1-25)"))
return (k,plaintext)
def reverseMsg(plaintext):
msgReversed=''
leng=len(plaintext)-1
for c in plaintext:
msgReversed+=plaintext[leng]
leng=leng-1
print(msgReversed)
return(msgReversed)
def encript(msgReversed,k):
cipher=''
for c in msgReversed:
if c in alphabet:
cipher+=alphabet[(alphabet.index(c)+k)%(len(alphabet))]
print(cipher)
(k,plaintext)=userInput()
reverseMsg(plaintext)
(cipher)=encript(msgReversed,k)
Error Message reads as follows`:
Line 26, in <module>
(cipher)=encript(msgReversed,k)
NameError: name 'msgReversed' is not defined

As mentioned in my comment, your variable msgReversed is not declared outside of your function, so it is not defined when you call it outside of it. In order to avoid posting duplicate answers, here is another approach:
I do not know if you have worked with classes before, but here is an example and pythons official documentation (https://docs.python.org/2/tutorial/classes.html)
class Encrypt:
def __init__(self):
(k,plaintext)=self.userInput()
self.reverseMsg(plaintext)
cipher =self.encript(self.msgReversed,k)
def userInput(self):
plaintext=input("Enter message to encript")
k=int(input("Enter encription Key you want to use (1-25)"))
return (k,plaintext)
def reverseMsg(self, plaintext):
self.msgReversed=''
leng=len(plaintext)-1
for c in plaintext:
self.msgReversed+=plaintext[leng]
leng=leng-1
print(self.msgReversed)
return(self.msgReversed)
def encript(slf, msgReversed, k):
alphabet=("abcdefghijklmnopqrstuvwxyz ")
cipher=''
for c in msgReversed:
if c in alphabet:
cipher += alphabet[(alphabet.index(c)+k)%(len(alphabet))]
print(cipher)
Encrypt()
As for Global variables, you can declare a global within a function. all you have to do is declare it global:
variable_name global
so your function with your variable msgReversed would be as follows:
def reverseMsg(plaintext):
global msgReversed
msgReversed = ''
leng=len(plaintext)-1
for c in plaintext:
msgReversed+=plaintext[leng]
leng=leng-1
print(msgReversed)
return(msgReversed)

Change your last few lines from this:
reverseMsg(plaintext)
(cipher)=encript(msgReversed,k)
To this:
(cipher)=encript(reverseMsg(plaintext),k)

In your last line you pass a variable called 'msgReversed' into your 'encript' function. However: msgReversed is only locally defined inside your 'reverseMsg' function. Variables can either be local variables that only live inside of a function. Or global variables, that live in the entire script. A simple workaround would be to make your msgReversed a global variable, by simply adding 'global' in front of the first line of your 'reverseMsg' function. Another solution in your first to last line:
msgReversed = reverseMsg(plaintext)
A simplified tutorial on this matter: http://www.python-course.eu/global_vs_local_variables.php
Added a simple example:
myname = "Marc"
def printName():
myname = "Sonder"
print (myname)
printName()
print (myname)
Outside of the function, the 'myname' function will yield "Marc". However inside the function, myname will yield "Sonder". If you would delete the first line, and try to execute the last line, to print the global version of 'myname', you will get the exact same error as you have got right now.
To grasp this I would copy this script, and see what changes when you comment certain parts out.

When you return the msgReversed variable from the reverseMsg() function, you need to assign it to a new variable in the outside scope.
msgReversed = reverseMsg(plaintext)
(cipher)=encript(msgReversed,k)
I suspect the confusion arises with the following line:
return msgReversed # Note, the brackets aren't required here
This returns from the function reverseMsg() while passing out the variable msgReversed. However, this variable isn't assigned anywhere by default — the name msgReversed is specific to the function. To store a value returned from a function you need to provide a variable name to store it in. Hence the following:
msgReversed = reverseMsg(plaintext)
...will store the value returned from your function in a new variable named msgReversed. You could also name that variable something else:
this_is_another_msgReversed = reverseMsg(plaintext)
If you don't provide a variable to assign the value to, it is simply lost:
reverseMsg(plaintext)
# No msgReversed variable here

Related

Getting name of local variable at runtime in Python3

I want to get variable name in function so here:
def foo(bar):
print(getLocalVaribalename(bar))
I want 'bar' to be printed.
so I found the code for global variables
def varName(variable,globalOrLocal=globals()):
for name in list(globalOrLocal.keys()):
expression = f'id({name})'
if id(variable) == eval(expression):
return name
and I sent varName(bar,locals()) to it like this
def foo(bar):
print(varName(bar,locals()))
but gives NameError: name 'bar' is not defined error.
I also found Getting name of local variable at runtime in Python which is for python 2 but the syntax is completely different. note that the main goal is to get the name of local variable and not necessarily with this code(varName function which is defined few lines earlier).
import sys
def getlocalnamesforobj(obj):
frame = sys._getframe(1)
return [key for key, value in frame.f_locals.items() if value is obj]
This introspects the local variables from the calling function.
One obvious problem is, of course, there might be more than one name pointing to the same object, so the function returns a list of names.
As put in the comments, however, I can't perceive how this can be of any use in any real code.
As a rule of thumb, if you need variable names as data (strings), you probably should be using a dictionary to store your data instead.

Assignment to variable in indent

Very simple problem (At least I think so): So I have a global variable, in this case test, and I want to assign an other value to it in a function. This is my code:
test = "Hello"
def launch():
test = "F"
launch()
print(test)
I wanted test to equal "F", but it doesn't. Instead, the output of this is that test still equals "Hello". I assume it creates a variable inside the function and then assigns a value to it.
But why does this work then:
test = {
"?": "Hallo"
}
def launch():
test["?"] = "F"
launch()
print(test)
The output of this is how I wanted it to be: test["?"] is equal to "F".
How is this working and why isn't the first code example?
Is there any way to use the first code how I wanted it to work?
You need to add a global test line to the top of the function to tell it to reference an existing variable instead of creating a new one. It's ambiguous otherwise.
Why does the second one work though? Because it isn't ambiguous. From context, it knows that you must be referencing an existing variable instead of attempting to create a new one.
test["?"] = "F"
is essentially
test.__setItem__("?", "F")
and that only makes sense if test already exists. It knows that you aren't trying to create a new local variable.
The language only requires a global test statement in cases where it can't tell whether or not you want to use an existing variable or create a new one.
In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, however, it’s assumed to be a local unless explicitly declared as global.
So, change it as follows:
test = "Hello"
def launch():
global test
test = "F"
In your second example you don't declare the dictionary (like test = {}). Hence, python looks for a global variable test. You can access global variables by:
def launch():
global test
test = "F"
In the first case, you're trying to access a global variable but you have also redeclared it as a local variable.
test = "Hello" #global variable by default.
def launch():
test = "F" # local variable by default. It's restricted to the function launch().
launch()
print(test) # Accessing global variable because print can't see test of launch.
test = "Hello" #global variable by default.
def launch():
global test
test = "F" # Accessing global value of test.
launch()
print(test) # Accessing global variable test.
In second case,you're assigning to a global variable, not redeclaring it as a local variable. There in lies the difference.
test = {'?':"Hello"} #global variable by default.
def launch():
test['?'] = "F" # global variable access by default. It's NOT restricted to the function launch().
launch()
print(test) # Accessing global variable.
In your first test, in your launch function, the test variable is recreated, with no link to the global function. It's a particularity of python.
If you wanted to change the global function you should have done like this :
def launch():
global test
test = 'F'
With your second test, test is a dictionary.
And yes, when you change a dictionary in a function without declaring it as a global variable, it changes the dictionary outside of the function as well.
If you want to know the real reason, it's way more complicated if you don't know C language... Python was programmed in C (for CPython at least), and in C, managing variables is very different than in Python.
In C, when you want to modify a variable in a function, you have to give to the function the memory address of the variable as a parameter (that variable is called a Pointer).
If you don't give the pointer of your global variable to the function where you want to modify it, it won't work.
When your launch function was called in your first example, test wasn't modified, because as you haven't declared test as global, python hasn't given the pointer of test to the launch function (only its value).
When you use dictionaries, Python will also give the value of the dictionary, but it will be a pointer to its elements. So you will be able to modify them.
That's why you can modify the elements in the dictionary, but you can't modify the dictionary. Example :
a = {"a":123, 'b':456}
def modif():
a = {"aa":123}
modif()
print(a)
results in:
{'a': 123, 'b': 456}
So the dictionary hasn't been modified. It works the same way with the lists (and I suppose with every iterable that support item assignment)
I tried to simplify, it's more complicated in reality, but it may teach you some thing I hope.

Global Variable declaration

I am kind of a beginner with Python and have dealt with the concept of a global variable. When I thought I understood the concept, I saw a short code which proved me wrong:
message="global"
def enclosure():
message="enclosure"
def local():
global message
message="local"
local()
print(message)
print(message)
enclosure()
print(message)
The output of that is:
global
enclosure
local
I dont understand, why the second output is enclosure, because when you call the enclosure function, within this function the funciton local is called, in which the global variable message is set to "local", which then as of my understanding should be printed out at the end when calling the enclosure function (so i would expect global, local, local..).
So where is my thinking error?
When you assigned message="enclosure" in enclosure, you made message a local variable for that scope. It doesn't matter that the nested function changed the global message; enclosure didn't declare message global, so it maintains its own locally scoped variable independent of the global one (that local shares).
In general, you should try to avoid global variables if possible. There is usually a cleaner way to achieve what you want.
In your example, you have two string variables, both called message. One has the scope of the whole module, it is initially bound to the value "global" and then inside the local method it is rebound to the value "local".
The second variable is also called message and has the scope of the enclosure method. It is initially set to the value "enclosure" and is not modified.
Your first print call is at module scope, so prints the value of the module-scoped message, which is "global". Your second call is inside the enclosure so prints the value of the other variable which is "enclosure". And finally you print the value of the module-scoped message which has now been changed to the value "local".
In reality you have two variables, for clarity I added a suffix 1 and 2:
message1="global"
def enclosure():
message2="enclosure" # this is a new declaration, it is a new message.
def local():
global message1
message1="local"
local()
print(message2) # in this scope, only message2 is visible
print(message1)
enclosure()
print(message1)
So you see, you created two message, and you use at the second print the second variable named message
i hope this will help you:
def generate_closure(income_tax_rate = 0.33):
def this_is_closure_which_will_give_final_money(raw_income):
final_money = raw_income - (raw_income * income_tax_rate)
return final_money
return this_is_closure_which_will_give_final_money
standard_tax_calculator = generate_closure()
classic_salary = standard_tax_calculator(2000)
final_classic_money = print(classic_salary)
classic_salary_2 = standard_tax_calculator(2499)
final_classic_money_2 = print(classic_salary_2)
rich_people_tax_calculator = generate_closure(income_tax_rate = 0.50)
rich_salary = rich_people_tax_calculator(15000)
final_rich_money = print(rich_salary)
rich_salary_2 = rich_people_tax_calculator(19499)
final_rich_money_2 = print(rich_salary_2)
print("\n------------------------------")
def generate_closure(trapped):
def closure(x):
return trapped ** x
return closure
f = generate_closure(10)
print(f)
f(3)
print(f(3)) # f remember the value 10
del generate_closure
print(f(2)) # it still does work !
print(f.__closure__[0].cell_contents) # here is the hidden value
Here is a function which return another function.
A closure is not a variable.
A closure aims at avoid using global variable.
Take care not to use key-word the wrong way.
You can think to use closure when some argument it will use are known to be constant.

functions in python - need explanation

can someone simply explain functions in python? I just can't get my head around them.
So I have had a go at them, and this is what I've ended up with, but it keeps saying that character is not a global variable
def char_name():
character = input("Enter character name: ")
return character;
def main():
char_name()
print(character)
main()
Can anyone explain functions?
This part is a function:
def char_name():
character = input("Enter character name: ")
return character;
It's important to realize that the variable character exists only inside the function. Not outside of it. That's a great feature -- it means that if you decide that name is a better name for the variable after all, then you only need to change the variables inside the function, and guaranteed nowhere else. No assignments to variables elsewhere can influence what happens in your function. It's all there.
The function has a return value equal to the value of the variable at the end of the function.
def main():
char_name()
print(character)
And here's another function, that also tries to have a variable named character. It happens to have the same name, but that's just a coincedence, it's a different function so it's a different variable. Unfortunately, this variable is only used but never set to any value, and Python can't find it as a global variable either, so it throws an exception. char_name is called, but its return value is not used for anything, so it's discarded.
What you want to do is this:
def main():
name = char_name() # I picked a different name to make my point
print(name)
The function char_name is called, and its return value is assigned to the variable name. Now you can print it.
def char_name():
character = input("Enter character name: ")
return character
def main():
character = char_name()
print(character)
main()
You need to assign returned values.

Python: local variable 'string' referenced before assignment

I was wondering why i was getting this error for adding a letter to this string from a function.
local variable 'string' referenced before assignment
CODE
def update_string():
string+='d'
string='s'
update_string()
You are accessing global variable, need to declare it:
def update_string():
global string # <<< declare `string` as global variable.
string+='d'
string='s'
update_varibles()
There is nowhere for the old 'string' to come from in the local scope of your function, so python assumes you're talking about the one from the outer scope.
Moreover, since strings are immutable the usual pattern is to create a new one and return it, so you might prefer to update your function interface to something more like:
def update_string(str_in):
return str_in + 'd'
And then you would use it instead like:
my_string = update_string(my_string)
You can access the variable from the outer scope inside the function, but you can't assign to it. So the following is a workaround without using global variables or inputs to the function:
def update_string():
updated=string+"d"
return updated
string="s"
string=update_string()

Categories