def main():
tests = get_initial_input(tests)
assignments = get_initial_input(assignments)
exercises = get_initial_input(exercises)
labs = get_initial_input(labs)
finals = get_initial_input(finals)
print(tests, assignments, labs)
def get_initial_input(x):
val = int(input("How many", x , "were there? "))
return val
main()
I keep getting an error:
UnboundLocalError: local variable 'tests' referenced before assignment
I've tried many different things to try to get tests to go to get_initial_input() but it says that it is referenced before assignment.
How is that possible when the first line of code I'm trying to define it?
When you use:
tests = get_initial_input(tests)
the first thing that happens is that Python tries to evaluate this:
get_initial_input(tests)
But tests is not defined yet, so you get an UnboundLocalError.
I think you are trying to pass a string to your function, which is used in the input prompt. A literal string is always surrounded by quotes.
tests = get_initial_input("tests")
This would be easier to debug if you'd used a proper variable name - eg label - in your function argument.
You are passing unassigned variable tests to get_initial_input() function. So, that's why you receive the error.
If you need a default value inside get_initial_input() function for x argument, then define it explicitly:
def get_initial_input(x=5):
...
And in main() call it for tests variable without arguments:
tests = get_initial_input()
If you need names (e.g. 'How many tests') - then pass strings, not cars to the function:
tests = get_initial_input('tests')
Related
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.
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.
My code is this:
word = input('enter a word:')
for letter in word:
print( letter)
Output:
enter a word:tree
t
r
e
e
Is letter an in-built variable?
You don't need to declare variables in Python. The variable is defined in the for-loop directly. Python has only very few keywords. It is also not a built-in constant.
I recommend going through a Python tutorial. You might also want to try exercism.
Variable Annotations
The following stuff is only relevant for Python 3.6+. No matter which Python version you use, you can ignore it. If you are a very early beginner, you probably should ignore it.
You can use variable annotations to "declare" a variable. PEP 526 introduces them. They look like this:
foo: str
int: bar
Python is a language which doesn't require to declare variables beforehand, like Pascal or any versions of C. In the moment you use a new variable, it is considered as being declared. In your case, letter is declared in the for loop.
"Variables declaration" in Python is implicit, in fact we better use name binding. There are many ways of name binding in Python, for is one of them.
For more details, you can have a look at binding-of-names.
There is one very important implicit fact: Python will pre-compute all names before executing code of one certain scope.
def test_1():
b = a + 1
def test_2():
b = a + 1
for a in range(3):
print(a)
# NameError: name 'a' is not defined
test_1()
# UnboundLocalError: local variable 'a' referenced before assignment
test_2()
In test_1, when executing b = a + 1, the error is name 'a' is not defined.
In test_2, when executing b = a + 1, the error is local variable 'a' referenced before assignment. That is to say, in test_2, when executing b = a + 1, Python already knew that a is a local variable, it just has not been bound to an object, so the error is UnboundLocalError.
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
I've written this code, and I want to be able to use the dictionary I created in the function as an argument for another function but I can't seem to print it on it's own, or use it as an argument as 'names is not defined'.
How do I create the same output (a list of dictionaries with dictionaries as values) but also being able to use the dictionary outside of the function?
def get_name(string_input):
l = [line.split('is connected to') for i, line in enumerate(string_input.split('.')) if i % 2 == 0]
names = {name[0]:{} for name in l}
return names
print get_name(example_input)
print names
You must assign the returned value
names = get_name(example_input)
print names
The variable names used inside the function is local, so not visible outside.
You are messing up with the variable scope of python.
A variable always has a scope where it is valid. Local variables which are declared inside a function are just valid inside that function.
In that example a is defined outside. Inside myFunc() there is also an a variable which has no reference to the a variable from outside. That means inside your computer memory a (outside) has a different part of the memory than a (inside myFunc).
a = "A String"
def myFunc(str):
a = str
return a
print myFunc("Hello World!") // Hello World!
print a // A String
A little bit more information about variable scopes in python:
Short Description of the Scoping Rules?