problem having with openpyexcel while making a password generator [duplicate] - python

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Why can a function modify some arguments as perceived by the caller, but not others?
(13 answers)
Closed 9 years ago.
This may seem like a really stupid question but I am confused regarding the scope rules in Python. In the following example I send two variables (x,y) with values to a function which is supposed to change their values. When I print the results the variables had not changed.
def func1(x,y):
x=200
y=300
x=2
y=3
func1(x,y)
print x,y #prints 2,3
Now if this were C++ I would send them by reference (&) to that function and therefore be able to change their values. So what's the equivilant in Python? and more important, what actually happens when you send objects to function? does Python make new references to these objects?

Think of them as being part of the function. When the function ends, all its variables die too.
x=2
y=3
def func(x,y):
x=200
y=300
func(x,y) #inside this function, x=200 and y=300
#but by this line the function is over and those new values are discarded
print(x,y) #so this is looking at the outer scope again
If you want a function to modify a value in exactly the way you have written it, you could use a global but this is VERY bad practice.
def func(x,y):
global x #these tell the function to look at the outer scope
global y #and use those references to x and y, not the inner scope
x=200
y=300
func(x,y)
print(x,y) #prints 200 300
The problem with this is that it makes debugging a nightmare in the best case, and utterly incomprehensibly impossible in the worst case. Things like these are commonly known as "side effects" in functions -- setting a value you don't need set and doing so without explicitly returning it is kind of a Bad Thing. Generally the only functions you should write that modify items in-place are object methods (things like [].append() modify the list because it's silly to return a new list instead!)
The RIGHT way to do something like this would be to use a return value. Try something like
def func(x,y):
x = x+200 #this can be written x += 200
y = y+300 #as above: y += 300
return (x,y) #returns a tuple (x,y)
x = 2
y = 3
func(x,y) # returns (202, 303)
print(x,y) #prints 2 3
Why didn't that work? Well because you never told the program to DO anything with that tuple (202, 303), just to calculate it. Let's assign it now
#func as defined above
x=2 ; y=3
x,y = func(x,y) #this unpacks the tuple (202,303) into two values and x and y
print(x,y) #prints 202 303

Related

Out-print of a function-call [duplicate]

This question already has answers here:
Modifying a list inside a function
(4 answers)
Closed 2 years ago.
I am currently new to python and I'm still learning the basics, but there is one thing I just can't wrap my head around. Why is the code in Q.1 giving the out-print 3, while Q.2 is giving the out-print [4]?
When asked, I was told that the f(x)-line at the bottom of Q.1 isn't given any variable or box to hold the new return-value given from the def. and that's the reason why the out-print of x remain 3.
This made sense to me, but then why would the out-print in Q.2 equal the return-value of g(x)? There isn't any variable or box to contain the return-value of x in this code either..
Q.1:
def f(x):
x += 1
return x
x=3
f(x)
print(x)
Q.2:
def g(x):
x[0] = x[0] + 1
return x
x = [3]
g(x)
print(x)
A Python function takes arguments by reference (something that points to the real object) whenever that argument is "complex", and takes the argument by value (a copy of the item) when it's a simple thing.
Q.1 is taking an int as an argument, then the function creates an internal copy of it and thus does not modify the value of x outside the function.
Q.2 is taking a list as an argument, which is considered complex, in which case the function takes a reference to the original and whatever happens to that reference will also happen to the original.
You can find an explanation of pass-by-reference and pass-by-value with images here
In Python, lists are mutable objects, and as a result they are passed-by-reference when used in a function call. This means that when g(x) adds 1 to the first element of x, after the function exits, the original list x will contain those changes.
Note that the specific term used is not "pass-by-reference", but rather "pass-by-name", which comes with a couple different semantics, which you can learn more about if you wish.
The function defined is Q1 is returning a value of for. x contains 3 and is passed into the function, by calling it with f(x). It gets incremented and returned to the function call. But, the function call was not stored in a variable, so it was not saved into memory. Nothing was done with the returned value. Calling the function is only editing the variable x within the local scope (within the function). When you're using print(x) it is referencing the global variable of x, which still contains 3.
In Q2, lists are mutable. Editing them within a function, the changes persist in the global scope. Because that list is mutated in the global scope, using print(x) uses the updated global variable.
I hope this makes sense. Look into scope of variables in the documentation for more.
Q1
def f(x):
x += 1
return x
x=3
f(x)
print(x)
The reason this is returning 3 and not 4 is because you haven't rebound your variable to reference this new value. Instead of f(x) you can do x = f(x).
Q2
def g(var):
var[0] = var[0] + 1
return var
x = [3]
g(x)
print(x)
To answer this without making it confusing I've changed the local variable used in the function to var so you can see what I'm trying to explain to you easier.
First you are creating a list with a integer value 3 in the first spot in the list (element 0) and you make x reference this list.
When you call g() function and pass the list, the function sets var to reference the same list (not a different one, the same one). You then tell the function to increase the integer value in the first element by 1. Since lists are mutable with certain methods, you have already changed the list for both the local variable var, and the global variable x. This means that you actually don't need to use any return of the function because the list has been mutated in place.
Have a look at this video https://youtu.be/_AEJHKGk9ns where Ned Batchelder explains more about this.

Need help using a mutator function in python

So I need to use a mutator method to change elements of a list in Python. I would normally do this using a function that can return a value, but for this assignment we are not allowed to return any values in the function.
Here's an example of the general idea that i'm talking about
def changeX(x):
x = 5
x = 3
changeX(x)
print(x)
The output for this would obviously be 3 since I did not change x.
So my question is, how would I approach this assignment? I need to use the mutator method to modify my variable but I'm not sure how.
You get the results you do because you pass a primitive value into your "mutator" function.
If you pass in a list, you'll see that you can change the value in place:
def changeX(x):
x[0]=3
x = [1,2,3]
changeX(x)
print (x)
It will print [3,2,3]. Check it out:
https://repl.it/EIZW/0

How to change the scope of a variable in a function? Python [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Why can a function modify some arguments as perceived by the caller, but not others?
(13 answers)
Closed 9 years ago.
This may seem like a really stupid question but I am confused regarding the scope rules in Python. In the following example I send two variables (x,y) with values to a function which is supposed to change their values. When I print the results the variables had not changed.
def func1(x,y):
x=200
y=300
x=2
y=3
func1(x,y)
print x,y #prints 2,3
Now if this were C++ I would send them by reference (&) to that function and therefore be able to change their values. So what's the equivilant in Python? and more important, what actually happens when you send objects to function? does Python make new references to these objects?
Think of them as being part of the function. When the function ends, all its variables die too.
x=2
y=3
def func(x,y):
x=200
y=300
func(x,y) #inside this function, x=200 and y=300
#but by this line the function is over and those new values are discarded
print(x,y) #so this is looking at the outer scope again
If you want a function to modify a value in exactly the way you have written it, you could use a global but this is VERY bad practice.
def func(x,y):
global x #these tell the function to look at the outer scope
global y #and use those references to x and y, not the inner scope
x=200
y=300
func(x,y)
print(x,y) #prints 200 300
The problem with this is that it makes debugging a nightmare in the best case, and utterly incomprehensibly impossible in the worst case. Things like these are commonly known as "side effects" in functions -- setting a value you don't need set and doing so without explicitly returning it is kind of a Bad Thing. Generally the only functions you should write that modify items in-place are object methods (things like [].append() modify the list because it's silly to return a new list instead!)
The RIGHT way to do something like this would be to use a return value. Try something like
def func(x,y):
x = x+200 #this can be written x += 200
y = y+300 #as above: y += 300
return (x,y) #returns a tuple (x,y)
x = 2
y = 3
func(x,y) # returns (202, 303)
print(x,y) #prints 2 3
Why didn't that work? Well because you never told the program to DO anything with that tuple (202, 303), just to calculate it. Let's assign it now
#func as defined above
x=2 ; y=3
x,y = func(x,y) #this unpacks the tuple (202,303) into two values and x and y
print(x,y) #prints 202 303

Returning a Tuple in Python function

This function that I have written thus:
def simulate_turn(num_rolls, score, opponent_score):
"""This function takes in two scores and a number of die rolls and returns
what the two scores would be if num_rolls many dice were rolled. This takes
into account the swine swap, free bacon, and hog-wild."""
x = score
y = opponent_score
x += take_turn(num_rolls,opponent_score,select_dice(score,opponent_score))
if ifwillswap(x,y):
swap(x,y)
return x,y
When run in the interactive python shell (the function comes from a .py file), it is returning an int object instead of a tuple! What am I doing wrong? I am trying to have it turn a pair of values, not a single int object.
You already do return a pair of values. Even if you somehow broke x and y somewhere along the way and had something ridiculous like this:
def example():
return None, None
a = example()
a would still hold a reference to the tuple (None, None) after the execution of that function. So you are returning a tuple of two "somethings", the only question is what are those "somethings" and how you are storing them. There is no reason for you to think that your function returns an int however, because it doesn't. No matter what, with the syntax you've used, your function returns a tuple of two types. You could even just do return x, and that would return a one-item tuple. The comma prevents you from returning just an int.
My guess is that your function swap() is maybe setting your variable y equal to None and that you are perhaps misinterpreting the returned values. As others have said, I don't see how you can see anything but a tuple as the return.

Python create function in a loop capturing the loop variable [duplicate]

This question already has answers here:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 6 months ago.
What's going on here? I'm trying to create a list of functions:
def f(a,b):
return a*b
funcs = []
for i in range(0,10):
funcs.append(lambda x:f(i,x))
This isn't doing what I expect. I would expect the list to act like this:
funcs[3](3) = 9
funcs[0](5) = 0
But all the functions in the list seem to be identical, and be setting the fixed value to be 9:
funcs[3](3) = 27
funcs[3](1) = 9
funcs[2](6) = 54
Any ideas?
lambdas in python are closures.... the arguments you give it aren't going to be evaluated until the lambda is evaluated. At that time, i=9 regardless, because your iteration is finished.
The behavior you're looking for can be achieved with functools.partial
import functools
def f(a,b):
return a*b
funcs = []
for i in range(0,10):
funcs.append(functools.partial(f,i))
Yep, the usual "scoping problem" (actually a binding-later-than-you want problem, but it's often called by that name). You've already gotten the two best (because simplest) answers -- the "fake default" i=i solution, and functools.partial, so I'm only giving the third one of the classic three, the "factory lambda":
for i in range(0,10):
funcs.append((lambda i: lambda x: f(i, x))(i))
Personally I'd go with i=i if there's no risk of the functions in funcs being accidentally called with 2 parameters instead of just 1, but the factory function approach is worth considering when you need something a little bit richer than just pre-binding one arg.
There's only one i which is bound to each lambda, contrary to what you think. This is a common mistake.
One way to get what you want is:
for i in range(0,10):
funcs.append(lambda x, i=i: f(i, x))
Now you're creating a default parameter i in each lambda closure and binding to it the current value of the looping variable i.
All the lambdas end up being bound to the last one. See this question for a longer answer:
How do I create a list of Python lambdas (in a list comprehension/for loop)?
Considering the final value of i == 9
Like any good python function, it's going to use the value of the variable in the scope it was defined. Perhaps lambda: varname (being that it is a language construct) binds to the name, not the value, and evaluates that name at runtime?
Similar to:
i = 9
def foo():
print i
i = 10
foo()
I'd be quite interested in finding out of my answer is correct

Categories

Resources