Python newbie: How do I define 'nl' in my program? - python

New to coding and I'm challenging myself to write a program where the user inputs values into a list and sorts them by another input value. When I run the program, I get a traceback error saying that 'nl' is not defined. I think I may have something out of order or I'm not using something correctly. Some advice would be helpful!
def listsort(l1):
for num in l1:
n1 = []
if num <= inp:
n1.append(num)
for x in n1:
print(x, end=' ')
def newlist():
nl = []
while True:
l_inp = input('Add to list: ')
if l_inp == 'done':
return nl
else:
float(l_inp)
nl.append(l_inp)
continue
newlist()
inp = float(input('Enter a number: '))
print('These numbers are less than or equal to', inp)
listsort(nl)

n1 has a function only scope, means can be accessed only inside function.
Declare the variable as global n1 inside both functions.

nl is declared in newlist and you only have scope to that variable in that function, if you want to access it from outside then you should declare nl outside the function and send it as a parameter to "newlist"
error in python shell showing scope of nl

There are two scopes in Python namely local and global. A local scope variable is declared within a function an that cannot be accessed outside the function in which it is defined. You have defined 'nl' inside the function. So, you can't access that outside that function. Hence, the reason for that error

The answer to your question revolves around an idea called scope, and understanding scopes will make it much easier to figure out problems like this in the future. Everyone learns differently, so don't feel you have to know all this right now, but if you want to know the details, read on!
Scope
Each variable in your program exists in something called a scope. Here is a diagram of your program. It has three scopes - a global scope and a scope for each function, listsort and newlist. Every function has its own scope, and every Python file has its own global scope.
Which scope a variable ends up in depends on where it is introduced. Some ways for variables to be introduced are assignment (for example n1, nl, l_inp and inp are all assigned with the = symbol), as a for loop variable (for example num and x are loop variables) and as a function parameter (l1 is a function parameter). A variable lives in the tightest scope around where it is introduced.
You can see that scopes are nested. The function scopes are inside the global scope. This is important. You can see that the inp variable is in global scope, but it can still be used in the listsort scope because the listsort scope is inside the global scope. Code inside a function scope can "see out" to variables in the global scope. But code in the global scope can't "see in" to variables in function scope.
Okay, so how do I get the variables out of a function?
The variables in a function's scope go away when the function returns. But you can return the value of a variable. Your function newlist returns the value of nl. But where does that value go? Well, nowhere, because your program doesn't assign it to a variable. You can do that by writing:
nl = newlist()
That will save the value into a new variable called nl in the global scope. But this is a different variable from the nl in newlist. You can of course use any variable name you like, just because you stored this value in a variable called nl inside newlist doesn't mean you have to put it in a variable with the same name at the global scope. You could write:
gl = newlist()
And then later on use:
listsort(gl)
And that would work just as well.

Related

Changing globally defined list as locally

I have a question about the python variables. As you see below, I have defined with L a list
and with I an integer variable after that, i have added new number to list inside function as locally.I can use the changed list outside the function as globally; on the other hand same situation is not for the integer variable.
Can someone help me please ? What is the difference?
PS:I know that ,I use integer variable inside the function as local variable because of that, it doesn't change on global. but why not a list variable?
L=[]
I=5
def change_var(I,L):
I=10
L.append(12)
print('Inside function I',I)
print('Inside function L',L)
return I,L
change_var(I,L)
print('Outside function I',I)
print('Outside function L',L)
Result
>>>Inside function I 10
>>>Inside function L [12]
>>>Outside function I 5
>>>Outside function L [12]```
If a variable gets affected a value anywhere inside the body of a function (as in variable = ...), then it is considered to be local, unless you explicitely declare it global in this function.
You treat I and L very differently:
You assign a value to I in I = 10, so it is considered local, and so a different variable from the other, global I. The changes you make to it can't be reflected on the other, global I. If you wanted to act on the global I, you should have declared global I at the start of your function.
You don't assign anything to L, you just mutate the unique, already existing global list.
You would have to change the name of the variables you are using inside the function, since you are creating new variables for I and L when inside the function, if you don't. In my example, I have changed them to lowercase(i and l). Also, when you put a number/variable inside the function parenthesis, it sets the variables inside the function to that number/variable, rather than putting that number inside the variable. So, when you put change_var(I,L), it effectively running the function, but putting the lines i=I and l=L at the start, rather than replacing all is with Is. To fix this, you will have to make I global when inside the function, so it affects code outside of the function, and then make I equal i.
The full code would be
L=[]
I=5
def change_var(i,l):
i=10
l.append(12)
print('Inside function I',i)
print('Inside function L',l)
global I
I=i
return i,l
change_var(I,L)
print('Outside function I',I)
print('Outside function L',L)
The code should work, but I'm sorry if my explanation didn't make any sense - I'm still quite new to answering on Stack Overflow.

Confusing use of global in Mark Lutz's "Learning Python"

On page 551 of the 5th edition, there is the following file, named thismod.py:
var = 99
def local():
var = 0
def glob1():
global var
var+=1
def glob2():
var = 0
import thismod
thismod.var+=1
def glob3():
var = 0
import sys
glob = sys.modules['thismod']
glob.var+=1
def test():
print(var)
local(); glob1(); glob2(); glob3()
print(var)
After which the test is run in the terminal as follows:
>>> import thismod
>>> thismod.test()
99
102
>>> thismod.var
102
The use of the local() function makes perfect sense, as python makes a variable var in the local scope of the function local(). However I am lost when it comes to any uses of the global variables.
If I make a function as follows:
def nonglobal():
var+=1
I get an UnboundLocalError when running this function in the terminal. My current understanding is that the function would run, and first search the local scope of thismod.nonglobal, then, being unable to find an assignment to var in nonglobal(), would then search the global scope of the thismod.py file, wherein it would find thismod.var with the value of 99, but it does not. Running thismod.var immediately after in the terminal, however, yields the value as expected. Thus I clearly haven't understood what has happened with the global var declaration in glob1().
I had expected the above to happen also for the var = 0 line in glob2(), but instead this acts only as a local variable (to glob2()?), despite having had the code for glob1() run prior to the assignment. I had also thought that the import thismod line in glob2() would reset var to 99, but this is another thing that caught me off guard; if I comment out this line, the next line fails.
In short I haven't a clue what's going on with the global scope/imports here, despite having read this chapter of the book. I felt like I understood the discussion on globals and scope, but this example has shown me I do not. I appreciate any explanation and/or further reading that could help me sort this out.
Thanks.
Unless imported with the global keyword, variables in the global scope can only be used in a read-only capacity in any local function. Trying to write to them will produce an error.
Creating a local variable with the same name as a global variable, using the assignment operator =, will "shadow" the global variable (i.e. make the global variable unaccessible in favor of the local variable, with no other connection between them).
The arithmetic assignment operators (+=, -=, /=, etc.) play by weird rules as far as this scope is concerned. On one hand you're assigning to a variable, but on the other hand they're mutative, and global variables are read-only. Thus you get an error, unless you bring the global variable into local scope by using global first.
Admittedly, python has weird rules for this. Using global variables for read-only purposes is okay in general (you don't have to import them as global to use their value), except for when you shadow that variable at any point within the function, even if that point is after the point where you would be using its value. This probably has to do with how the function defines itself, when the def statement is executed:
var = 10
def a():
var2 = var
print(var2)
def b():
var2 = var # raises an error on this line, not the next one
var = var2
print(var)
a() # no errors, prints 10 as expected
b() # UnboundLocalError: local variable 'var' referenced before assignment
Long story short, you can use global variables in a read-only capacity all you like without doing anything special. To actually modify global variables (by reassignment; modifying the properties of global variables is fine), or to use global variables in any capacity while also using local variables which have the same name, you have to use the global keyword to bring them in.
As far as glob2() goes - the name thismod is not in the namespace (i.e. scope) until you import it into the namespace. Since thismod.var is a property of what is now a local variable, and not a global read-only variable, we can write to it just fine. The read-only restriction only really applies to global variables within the same file.
glob3() does effectively the same thing as glob2, except it references sys's list of imported modules rather than using the import keyword. This is basically the same behavior that import exhibits (albeit a gross oversimplification) - in general, modules are only loaded once, and trying to import them again (from anywhere, e.g. in multiple files) will get you the same instance that was imported the first time. importlib has ways to mess with that, but that's not immediately relevant.

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.

Scope in Python 3.6.And the Error [duplicate]

This question already has answers here:
Function not changing global variable
(4 answers)
Closed 5 years ago.
How does the code below give the output as None?
def funct(x):
x=7
x=11
x=test(x)
print(x)
Here is another code snippet:-
def func():
print (x)
x = 90
x = 1
func()
The output for this should be 90! The scope is searched as Local ,Enclosed , Global ,Build-in .Either x should here be searched as local or global
Please explain.
x here is not a global variable in the scope of the functions, as functions naturally create their own namespaces, which do not include any outer variables not passed in as a parameter.
There are many issues with your code, including the order of function calling, and the order of the operations inside the functions; but to answer your question in the broadest way possible, in order for you to access the x variable defined outside of your functions, in a greater scope that is, you need to reference its namespace, by prepending global x inside the body of each of your functions.
Read up on Python variables and scope, and recheck the other errors in your code I have stated above.
The first code snippet returns None for the simple fact that you didn't return any value from the function. You defined x as a local parameter, not a global variable. Since you didn't return any value, your call test(x) (which does not match the function name of funct), will become a value of None. This is clearly defined in the Python documentation. To get the local value back to your main program, try this:
test(x):
x = 7
return x
x = 11
x = test(x)
print(x)
Also, please note that your initial value of 11 is entirely ignored in the main program, and that your function ignores the value it's given. You should shorten this example to
func():
return 7
print(func())
Your second example will print the external value of 1 because you have not defined a local variable x at that point, and a function is allowed to reference global variables.
However, when you assign a value in the next, you create a local variable -- you have not declared x to be global, so you can't assign to the x in the main program.
Again, you do not return any value. Therefore, back in the main program, func() evaluates to None.
Does that clear up what happened?

Global array -- no need for "global" statement

I wrote this code:
sample_array = ones ([N, 3], dtype = float)
def get_training_set ():
r = rand (N, 2) * 2 - 1
sample_array[:,[0,1]] = r
return sample_array
I declared the sampling array outside, in order not to allocate it all the time, just to modify it -- the last coordinate is always 1.
Initially I expected that I have to insert a statement "global sample_array" in function, because I modify it, and consequently the evaluator should know that it's a global var.
But, to my surprise, it works well without "global". Why does it work ? Where/what is the definition of evaluation in this case ?
global is necessary if you are changing the reference to an object (e.g. with an assignment). It is not necessary if you are just mutating the object (e.g. with slice assignment like what you've done above).
The exact documentation is here.
The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals.
So, with the global statement, you're telling python that the variable lives in the global context. If you assign to it, then you change the value in the global context.
If you don't use the global statement, python decides whether the variable is local or nonlocal. (In fact, python3.x added a nonlocal keyword). The variable is nonlocal if it appears first on the right side of an assignment, or if you do item assignment (x[...] = ...) or attribute assignment (x.whatever = ...). If the variable is local, that means that it was created in the function (or is an input argument). You can reassign directly to a local identifier and there's no problem. If the variable is non-local, you can mutate it, but you can't re-assign it because then python is unable to determine whether the variable is local or non-local.
I think it's because sample_array is not declared inside the function, but just write.
Python cannot find sample_array in side function namespace, it will find the outer namespace.
E.g.
a = []
def test1():
a.append(1) # will use the outer one
def test2():
a = []
a.append(1) # will use the inner one
Global, sometimes, for declare a global variable:
def declare_global():
global b # this should be global after 'declare_global()' is called
b = 1
print b # raise NameError: name 'b' is not defined
declare_global()
print b # will output '1'

Categories