So I have this function (example):
def monty(x):
if abs(int(x)) == 1:
print("Cool!")
print("Took %s attempts.") % (z)
elif abs(int(x)) == 0:
print("Nope.")
else:
z = z + 1
y = x - 1
monty(y)
Now, of course, 'z' has not yet been defined, so when this function is run so that the 'else' statement is called, the program returns a NameError exception.
Well, ok. Let's try making the statement this:
else:
try: z
except NameError: z = 0
else: z = z + 1
y = x - 1
monty(y)
Also assume we added the same NameError catch to the 'if' statement.
The statement always returns 'z' as 0, as the variable is utterly forgotten when 'monty' is ran again. Ok, what if we try defining z outside of 'monty' first, and drop the NameError catch?
Well, it returns a NameError again, and if we instead keep the NameError catch, it still only ever outputs 0.
So, how do I make the function increase z every time it's called validly? In other words, how can I have the program silently count how many times a function was run, to be recalled later? Let's try to avoid adding another argument to the function, for the sake of user-friendliness.
Just add z as a keyword argument:
def monty(x, _z=0):
# ...
else:
_z = _z + 1
y = x - 1
monty(y, _z)
I renamed z to _z to indicate that it is an implementation detail the end-user doesn't need to worry about. Because keyword arguments have a default, the caller of monty() doesn't have to worry about it.
Related
This question already has answers here:
How can a name be "unbound" in Python? What code can cause an `UnboundLocalError`?
(3 answers)
Closed last year.
This Python program will determine whether the input array is a mountain array or not. I've found answers on stackoverflow for this same error in other programs I've made, but not this one. It seems to work without issue when a valid mountain array is the input, but I'm having issues when I change the first half of the test array to make it an invalid. Rather than it returning False, which is the goal, I'm getting this error: UnboundLocalError: local variable 'y' referenced before assignment. Also, I was getting the same error for the z variable, so I added the else statements and it fixed it. Can't figure out why it didn't fix the y variable as well. Here's my code:
def validMountainArray(arr):
maxElem = max(arr)
maxIndex = arr.index(maxElem)
if len(arr) < 3:
return False
else:
beginning = arr[:maxIndex]
end = arr[maxIndex + 1:]
for i in range(1, len(beginning) - 1):
if beginning[i + 1] > beginning[i]:
y = True
else:
y = False
for i in range(1, len(end) - 1):
if end[i + 1] < end[i]:
z = True
else:
z = False
if y == True and z == True:
return True
else:
return False
Those for-loops aren't guaranteed to be executed. It's possible that the range could end up with 0 numbers in it, and thus no loop will occur and y and/or z will never be assigned. To fix this, define those variables as False at the start of the function.
def validMountainArray(arr):
y = False
z = False
maxElem = max(arr)
maxIndex = arr.index(maxElem)
# etc
Function should count how much expression as y is in request and if there is no y in request function should return "there is no y in request". I need to reduse else return expression, but in this case progran doestn't work properly.
I need to make expression as:
def foo():
number = 0
for x in request:
if x == y:
number += 1
return "there is no y in request"
return number
but even if x is y it gives "x is not y". If I use else like:
def foo():
number = 0
for x in request:
if x == y:
number += 1
else:
return "there is no y in request"
return number
But else return is against syntax rools. How to correct code?
I can see a few problems with this code:
It is clear that number is supposed to count the total occurrences of y in request. A return statement immediately terminates a function returning a value. When you want to iterate and process every element of request you need to continue the execution. That code does not work because it stops at the first element which is not y and returns, instead to continue.
y is not defined
Semantically, a function is reusable because of the arguments you may pass in order to vary its calls depending on your needs
The following works:
y = 5
def foo(request):
number = 0
for x in request:
if x is y:
number += 1
return "there is no y in request" if number == 0 else number
foo([1,2,5])
This could be super simple but I can’t think of a solution. I want to be able to change a variable outside of a if statement. I have this in a try loop.
For example:
Try:
X = 0
If char == ord (‘w’):
X += 1
The only problem is that once it runs again the value of x will return to 0. How do I reassign the value of x to be the new number?
assign as an argument of the function what you want to change from one side and inside of the function make sure to use "return" the value that you want to be changed.
Once done push the same returned as an argument, with a loop most likely.
def function_name(x):
x +=1
print('New X Value',x)
return x
for i in range(5):
function_name(i)
Is there a way to do variable assignments(as shown below) using ternary operators in python:
if(x>1):
y="yes"
else:
z="yes"
Something like (x='yes') if(x>1) else (z='yes'), but this gives an error. Is there any other way to do this?
I know single variable assignments can be done like this: x="yes" if(l==0) else "no"
Edit: Assume x, y & z are assigned with some value before this is run.
You can use the following hack, which employs tuple unpacking:
y, z = ('yes', z) if x > 1 else (y, 'yes')
Don't miss those parentheses.
I wouldn't really recommend using this as it is harder to understand, has one redundant assignment statements, and uses unpacking unnecessarily. I'd recommend going for the normal if statement wherever you can.
This is what it would be with normal ifs:
if x > 1:
y = 'yes'
z = z
else:
y = y
z = 'yes'
No, you can't do that. You can only have expressions, not statements, inside the ternary. print works because (in Python 3 at least) it is a function call, therefore an expression; but assignment is always a statement.
varname = 'y' if x > 1 else 'z'
If you want to assign a global variable:
globals()[varname] = 'yes'
If you want to set an attribute on an object:
setattr(obj, varname, 'yes')
If it's a local variable inside a function, you have to get more hacky:
exec('%s = "yes"' % varname)
or
exec(varname + ' = "yes"')
You can of course place the definition of varname directly in all of these statements to keep it in one line, I'm just avoiding repetition.
But really it's best to not do any of these. Keep it simple and straightforward.
You can use exec function like this:
exec("y='yes'" if x > 1 else "z='yes'")
I'm making a double variable if statement and it keeps returning an error. I don't know what's wrong:
variable = float(0)
for index in range(10):
variable = variable + float(2)
if x <= float(variable/3) and > float(variable-2.0/3):
# do something
else:
pass
or something like that. This is the basic structure. Why does it keep highlighting the > in red whenever I try to run it?
Python supports regular inequalities as well, so you could just write this:
if variable - 2.0 / 3 < x <= variable / 3:
# ...
You want to do something like
if ((x <= float(variable/3)) and (x > float(variable-2.0/3))):
# do something
else:
pass
In other words, each side of the and must be a boolean expression on its own. I'm not sure whether you need all the parenthesis.
It seems like you're missing a variable or constant before the second condition in the if-block. That might be one reason you're getting an error.
This code works fine:
index=0
x=0
variable = float(0)
for index in range(10):
variable=variable + float(2)
if x <= float(variable/3) and x> float(variable-2.0/3):
print 'Doesn\'t Matter'
else:
print 'pass'