I'm new to programming and have just hit my first speed bump since starting this semester. We have been working in python and our latest assignment has us altering a previous program to use functions. I am understanding how to use them and what not, but some small things with local variables I think I lack in some conceptual understanding.
I use pycharm to write my assignments, and I can see it states one of my variables is unused and I don't understand why or how to fix it. I've been tinkering for a couple hours and am lost.
# Function "checkName" takes in 2 parameters
# The first is name, which will be given by user input
# The second is nameList, which comes from the function getNamesList
def checkName(name, nameList):
for i in range(0, len(nameList)):
if name == nameList[i]:
rank = i + 1
break
else:
rank = 0 ## This rank is undefined ##
return rank
Any pointers on what I'm doing wrong? An explanation of the differences between defining local and global variables would be appreciated as well!
You get the error "Local variable 'rank' value not used" on the line rank = i + 1 because the the break statement on the next line causes the the function to end without ever reading the value from rank. This is only the case because your return statement is indented too far. Move it back one level of indentation so it doesn't return until the loop is done and the warning will go away.
def checkName(name, nameList):
for i in range(0, len(nameList)):
if name == nameList[i]:
rank = i + 1
break
else:
rank = 0 ## This rank is undefined ##
return rank
I can tell you that if you hit your 'break' statement, you're not going to be returning anything, because you've got your indentation wrong. You need to take one indentation out of your return.
I can also tell you a little bit about global and local variables, in lay-terms: Any variable you define inside your function, such as 'rank', will not persist outside the function. If you run the above and then try to call 'rank' outside of your function, you'll be calling a blank variable (unless you specifically named another variable 'rank'). This enables you to use rank inside the function without fearing conflict with variables outside the function. In general, you want to avoid making any truly 'global' variables, but a variable named outside of a function is more 'global' than one named inside one.
As for what pyCharm is flagging, I'm not sure, because I don't use the program. Are you calling your function anywhere? It could be letting you know that you're defining your function, and then not calling it.
By reading your code, I understand that this functions returns the rank or the index of a name in a given list of names.
You have a wrong indentation on the return statement.
So to improve your code, check this:
def checkName(name, nameList):
for i in range(nameList):
if name == nameList[i]:
return i + 1
# you don't need an else here, just return -1 or 0 or None ( by default )
# whenever `name` doesn't exists on the nameList
# not very pythonic
return 0
Your code was not always using the local variable rank because of the wrong indentation.
From the point of view of the code as written, rank is defined but not used - you set it and break, so it looks like nothing is done with it. Once again, it's that indent others have mentioned.
Thank you all very much for the quick and helpful replies! My indentation was off, silly error. Honestly don't know how I overlooked it so many times.
I also appreciate the distinction on local variables. I think my previous understanding was alright, but the pycharm note i was getting threw me for a loop.
Probably the shortest it can be:
nameList = ["a", "b", "c"]
def checkName(name, nameList):
return(nameList.index(name) + 1 if name in nameList else 0)
for i in ["a", "b", "c", "d"]:
print(checkName(i, nameList))
Result:
1
2
3
0
Related
so basically I have encountered a problem where I have made my loop, but since one of the variables is defined before the actual assignment, the code stops working. the code.
Another thing is that I'm working in Spyder, and I don't know why, but if I try to code so that the program collect variables initially (which is essential for this purpose), the program encounters an internal issue. Any ideas on how to ask for user input in Spyder?
Thanks to everyone in advance
Basically, what I want this to do is to differentiate functions, and the with these derivatives create a maclaurin series. When the actual error ((r-j)/r) is smaller than the stopping variable s, I want the program to stop and display the result, but I don't know what is wrong.
The second thing I want to achieve is to get to know how to gain input from the user in the program.
So, here is, in text form, your code (sorry, plagiarism argument is not valid around here)
q = sympy.Function('q')
q = sympy.diff(f)
def main():
a = sympy.Function('a')
a = sympy.diff(q)
j = sympy.function
j = 1+(1/sympy.factorial(count))*q
r = sympy.Function('r')
r = j+(1/sympy.factorial(count+1))*a
if ((r-j)/r)>s:
count = count + 1
q = sympy.diff(a)
j = r+(1/sympy.factorial(count))*q
r = j+(1/sympy.factorial(count+1))*a
main()
else:
print(f"Answer{r}")
In the middle of an obviously very confused code, and even more confused situation with that "plagiarism" stuff (don't worry, if you have a working code at the end of your effort, there is no way it will look similar enough to your original to be detected as plagiarism because I've posted it here:D) there is actually a good question, and I remember that I while ago I had to scratch my head to understand what was happening in a similar situation.
The problem you have here, is that you can't compute sympy.diff(q) in main function, before assigning something to q in that same function later.
Because of the line q = sympy.diff(a) that you have later, q has to be a local variable (unless you say otherwise, see later). That's default behavior in python: a variable that you assign in a function is a local variable.
But because you are reading this variable before, in the previous line (the one that triggers the error) a = sympy.diff(q), then python has a problem: the local variable a doesn't exist yet.
Without the future q = sympy.diff(a), q would have been "read-only" inside main, and python would have done what you probably expect: read the global variable q.
So, your real problem is not really that line. Your real problem is the line q = sympy.diff(a).
Because even without the current error, that line would not do what you expect it to do. You probably expect it to alter q so that in the subsequent recursive call of main, q has this new value for now on. Not to create a local value q, and have the next call of main start over with the global value of q.
You have several options here.
One would be to declare q has global. Just add line global q at the beginning of your main, and q is now the global variable.
A cleaner way would be to pass q as an argument to main.
Note that you'll have probably the same problem with count. You should also either declare it as global, or, neater way, pass it to main.
Note also that this would solve only syntax errors (well, not even all. j=sympy.function is meaningless for example). But there are many other errors here. The least serious being your strange habit to create a Function and immediately delete it by overwriting it by another function or expression.
This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 5 months ago.
I am confused about scope.
What, if anything, is the difference between assigning a variable 'within a function' and assigning one within an
indented block? I have read many places that if and try blocks do not create, or have, their own scope, but I have also
read that the scope of a variable is the innermost block where it is defined.
I googled but was not able to find an example of nonlocal inside an if or try block.
def sixdig2iso(pathfrom):
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
PyCharm says nonlocal variable 'xfrs' must be bound in an outer function scope
Isn't this the outermost part of this function? Then what's the problem?
Is the outermost part of this function != an outer function? Even if the scopes of each are different from the inner parts of those same functions?!
if xfrs == 0:
restofit = frs[1:]
try:
convert = datetime.strptime(mm, '%m%d%y')
except ValueError as e:
logger.info(f"For {filename}, mm is: {mm} - and the error is: {e}")
count_err += 1
ender = ' '.join(restofit)
fronter = str(convert.date())
PyCharm says the 2nd convert 'might' be used before assignment
I tried making an inner function
def sixdig2iso(pathfrom):
"""Converts six digit dates into proper datetime format in place."""
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
def blockscope():
But PyCharm gives me the same "nonlocal variable 'xfrs' must be bound in an outer function scope" warning.
UPDATE
My response is too long for a comment.
“We have to guess because you didn't provide a complete example”
I can never seem to get the balance between ‘not enough’ and ‘too much’ information for these questions. I probably didn’t think the part you say is missing was relevant, which goes to my understanding of the problem in the first place.
“ it doesn't matter how many nestings of function you create inside this function, nonlocal only looks outward.“
See, I didn’t know that. And I infer, then, it only looks ‘upward’, too, right?
“As .strptime() might fail with an exception, convert may end up not having been assigned a value, as you did not initialise convert outside the try block. “
Ok, good, that is very helpful. I didn’t realize (and PyCharm does not explain as you just did) this is what PyCharm was talking about. But this is also why I was confused about the ‘scope’ of a try block.
In the first example you give, xfrs is only defined in the function you've provided as an example. We have to guess because you didn't provide a complete example, but the message from PyCharm suggests that you did not define this function inside another function that already had such an identifier defined in it and there's no xfrs in the global scope either.
In the second example, you assign to convert in the try section of a try .. except block. As .strptime() might fail with an exception, convert may end up not having been assigned a value, as you did not initialise convert outside the try block. So, PyCharm is correct (again, we have to assume as you did not provide a complete example.
Finally, in the third example, you start defining a function inside the function, but still apply nonlocal to a variable in the sixdig2iso() scope - it doesn't matter how many nestings of function you create inside this function, nonlocal only looks outward.
A typical use of nonlocal is as #Carcigenicate provides in their link (some modifications here):
x = 0
def outer():
x = 1
def inner():
nonlocal x
x += 1
return x
return x, inner
v, f = outer()
print(x, v, f())
The function returned by outer() produces 2 when called, as its non-local variable x of inner() is the same as the local variable x of outer(), starting at 1 and having 1 added as the function is called.
You can tell that is what happens, as the value returned by outer() is 1, but calling the returned function f() returns 2. All the time, the global x is untouched.
Try changing nonlocal to global and you'll find the the result changes from:
0 1 2
To:
0 1 1
I hope that helps explain what is going on with nonlocal.
So I came across a recursive solution to a problem that keeps track of a global variable differently than I've seen before. I am aware of two ways:
One being by using the global keyword:
count = 0
def global_rec(counter):
global count
count += 1
# do stuff
print(count)
And another using default variables:
def variable_recursive(counter, count=0):
count += 1
if counter <= 0:
return count
return variable_recursive(counter-1, count)
The new way:
#driver function
def driver(counter):
#recursive function being called here
rec_utility.result = 0 <---initializing
rec_utility(counter) <--- calling the recursive function
print(rec_utility.result)
def rec_utility(counter):
if counter <= 0:
return
rec_utility.result += 1 <---- 'what is happening here'
rec_utility(counter-1)
I find this way a lot simpler, as in default variable method we have to return the variables we want to keep a track of and the code get really messy really fast. Can someone please explain why passing a variable joint to a function, like an object property works? I understand that python functions are nothing but objects, but is this a hacky way of keeping track of the variables or is it common practice? If so why do we have so many ways to achieve the same task? Thanks!
This isn't as magical as you might think. It might be poor practice.
rec_utility is just a variable in your namespace which happens to be a function. dir() will show it listed when it is in scope. As an object it can have new fields set. dir(rec_utility) will show these new fields, along with __code__ and others.
Like any object, you can set a new field value, as you are doing in your code. There is only one rec_utility function, even though you call it recursively, so its the same field when you initialize it and when you modify it.
Once you understand it, you can decide if it is a good idea. It might be less confusing or error prone to use a parameter.
In some sense, this question has nothing to do with recursive functions. Suppose a function requires an item of information to operate correctly, then do you:
provide it via a global; or
pass it in as a parameter; or
set it as a function attribute prior to calling it.
In the final case, it’s worth considering that it is not entirely robust:
def f():
# f is not this function!!
return f.x + 1
f.x = 100
for f in range(10): pass
Generally, we would consider the second option the best one. There’s nothing special really about its recursive nature, other than the need to provide state, which is information, to the next invocation.
for i in range(10):
s = 5
for j in range(10):
s = min(s)
The above code gives the title of this question as warning in IntelliJ for the second line.
I'm pretty sure that the warning happens because in the CFG there are possibly two consecutive writes (without read in between) to s because of the nested loops. Until now I have been ignoring the warning but to be on the safe side I'd like to ask for confirmation of my hypothesis.
Your hypothesis is nearly correct. The name s was bounded to an integer whose value was never used nor changed in the enclosing loop and yet it is rebounded to another value (although that will raise an error) in the nested loop. Note that the first assignment does not change with any iteration of the outer for loop.
The IDE's warning suggests the first assignment inside the loop is unnecessary as s was never changed. The assignment might as well have been better placed outside the for loop which will prevent a redundant binding and rebinding:
s = 5
for i in range(10):
...
It is what it says.
You remade something without using it or defining it.
Like for me, example:
def car(e):
color = "blue"
print(color)
def car(r):
Run
Error, I redefine the function, can't do that as far as I know, I didn't make it do anything.
Thought I was using the function, didn't realize I was re defining it.
correction
def car(e):
color = "blue"
print(color)
car(e)
I have a function in a program that I`m working at and I named a variable inside this function and I wanted to make it global. For example:
def test():
a = 1
return a
test()
print (a)
And I just can`t access "a" because it keeps saying that a is not defined.
Any help would be great, thanks.
I have made some changes in your function.
def test():
# Here I'm making a variable as Global
global a
a = 1
return a
Now if you do
print (a)
it outputs
1
As Vaibhav Mule answered, you can create a global variable inside a function but the question is why would you?
First of all, you should be careful with using any kind of global variable, as it might be considered as a bad practice for this. Creating a global from a function is even worse. It will make the code extremely unreadable and hard to understand. Imagine, you are reading the code where some random a is used. You first have to find where that thing was created, and then try to find out what happens to it during the program execution. If the code is not small, you will be doomed.
So the answer is to your question is simply use global a before assignment but you shouldn't.
BTW, If you want c++'s static variable like feature, check this question out.
First, it is important to ask 'why' would one want that? Essentially what a function returns is a 'local computation' (normally). Having said so - if I have to use return 'value' of a function in a 'global scope', it's simply easier to 'assign it to a global variable. For example in your case
def test():
a = 1 # valid this 'a' is local
return a
a = test() # valid this 'a' is global
print(a)
Still, it's important to ask 'why' would I want to do that, normally?