How do I fix this while loop? [duplicate] - python

I have noticed that it's common for beginners to have the following simple logical error. Since they genuinely don't understand the problem, a) their questions can't really be said to be caused by a typo (a full explanation would be useful); b) they lack the understanding necessary to create a proper example, explain the problem with proper terminology, and ask clearly. So, I am asking on their behalf, to make a canonical duplicate target.
Consider this code example:
x = 1
y = x + 2
for _ in range(5):
x = x * 2 # so it will be 2 the first time, then 4, then 8, then 16, then 32
print(y)
Each time through the loop, x is doubled. Since y was defined as x + 2, why doesn't it change when x changes? How can I make it so that the value is automatically updated, and I get the expected output
4
6
10
18
34
?

Declarative programming
Many beginners expect Python to work this way, but it does not. Worse, they may inconsistently expect it to work that way. Carefully consider this line from the example:
x = x * 2
If assignments were like mathematical formulas, we'd have to solve for x here. The only possible (numeric) value for x would be zero, since any other number is not equal to twice that number. And how should we account for the fact that the code previously says x = 1? Isn't that a contradiction? Should we get an error message for trying to define x two different ways? Or expect x to blow up to infinity, as the program keeps trying to double the old value of x
Of course, none of those things happen. Like most programming languages in common use, Python is a declarative language, meaning that lines of code describe actions that occur in a defined order. Where there is a loop, the code inside the loop is repeated; where there is something like if/else, some code might be skipped; but in general, code within the same "block" simply happens in the order that it's written.
In the example, first x = 1 happens, so x is equal to 1. Then y = x + 2 happens, which makes y equal to 3 for the time being. This happened because of the assignment, not because of x having a value. Thus, when x changes later on in the code, that does not cause y to change.
Going with the (control) flow
So, how do we make y change? The simplest answer is: the same way that we gave it this value in the first place - by assignment, using =. In fact, thinking about the x = x * 2 code again, we already have seen how to do this.
In the example code, we want y to change multiple times - once each time through the loop, since that is where print(y) happens. What value should be assigned? It depends on x - the current value of x at that point in the process, which is determined by using... x. Just like how x = x * 2 checks the existing value of x, doubles it, and changes x to that doubled result, so we can write y = x + 2 to check the existing value of x, add two, and change y to be that new value.
Thus:
x = 1
for _ in range(5):
x = x * 2
y = x + 2
print(y)
All that changed is that the line y = x + 2 is now inside the loop. We want that update to happen every time that x = x * 2 happens, immediately after that happens (i.e., so that the change is made in time for the print(y)). So, that directly tells us where the code needs to go.
defining relationships
Suppose there were multiple places in the program where x changes:
x = x * 2
y = x + 2
print(y)
x = 24
y = x + 2
print(y)
Eventually, it will get annoying to remember to update y after every line of code that changes x. It's also a potential source of bugs, that will get worse as the program grows.
In the original code, the idea behind writing y = x + 2 was to express a relationship between x and y: we want the code to treat y as if it meant the same thing as x + 2, anywhere that it appears. In mathematical terms, we want to treat y as a function of x.
In Python, like most other programming languages, we express the mathematical concept of a function, using something called... a function. In Python specifically, we use the def function to write functions. It looks like:
def y(z):
return z + 2
We can write whatever code we like inside the function, and when the function is "called", that code will run, much like our existing "top-level" code runs. When Python first encounters the block starting with def, though, it only creates a function from that code - it doesn't run the code yet.
So, now we have something named y, which is a function that takes in some z value and gives back (i.e., returns) the result of calculating z + 2. We can call it by writing something like y(x), which will give it our existing x value and evaluate to the result of adding 2 to that value.
Notice that the z here is the function's own name for the value was passed in, and it does not have to match our own name for that value. In fact, we don't have to have our own name for that value at all: for example, we can write y(1), and the function will compute 3.
What do we mean by "evaluating to", or "giving back", or "returning"? Simply, the code that calls the function is an expression, just like 1 + 2, and when the value is computed, it gets used in place, in the same way. So, for example, a = y(1) will make a be equal to 3:
The function receives a value 1, calling it z internally.
The function computes z + 2, i.e. 1 + 2, getting a result of 3.
The function returns the result of 3.
That means that y(1) evaluated to 3; thus, the code proceeds as if we had put 3 where the y(1) is.
Now we have the equivalent of a = 3.
For more about using functions, see How do I get a result (output) from a function? How can I use the result later?.
Going back to the beginning of this section, we can therefore use calls to y directly for our prints:
x = x * 2
print(y(x))
x = 24
print(y(x))
We don't need to "update" y when x changes; instead, we determine the value when and where it is used. Of course, we technically could have done that anyway: it only matters that y is "correct" at the points where it's actually used for something. But by using the function, the logic for the x + 2 calculation is wrapped up, given a name, and put in a single place. We don't need to write x + 2 every time. It looks trivial in this example, but y(x) would do the trick no matter how complicated the calculation is, as long as x is the only needed input. The calculation only needs to be written once: inside the function definition, and everything else just says y(x).
It's also possible to make the y function use the x value directly from our "top-level" code, rather than passing it in explicitly. This can be useful, but in the general case it gets complicated and can make code much harder to understand and prone to bugs. For a proper understanding, please read Using global variables in a function and Short description of the scoping rules?.

Related

Issue with function definition for Write and Call Some Simple Functions [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I know you guys are not here to do my homework for me, but I just don't have enough python program knowledge to resolve the assignment. I tried, but it doesn't seems working. Can you please help me out? Below is the assignment.
Assignment instruction:
Page 1 of 3
Instructions
Examine the starter code in the code editor window and understand what it is doing.
Content of the exercise.py file is below which is in the editor window.
x = 3
y = 4
if x < y:
min_xy = x
else:
min_xy = y
print(min_xy)
a = 12.3
b = 13.7
if a < b:
min_ab = a
else:
min_ab = b
print(min_ab)
w = -3.9
z = -4.7
if w < z:
min_wz = w
else:
min_wz = z
print(min_wz)
Instructions
Now we want to write a Python function that carries out this repeated
operation, so that we can just write it once and call it repeatedly.
In the code editor, at the top of the file before the existing code,
write a function named find_min that takes two inputs and returns the
lesser of the two. Remember to use the def keyword to start the
definition of a new function, indent the body of the function under
the def line, and return the result at the end.
Start the ipython interpreter by typing ipython at the command prompt.
Run the exercise in the interpreter (%run exercise.py): you should see
some variables printed out from the starter code. Type %who to see
that the interpreter also knows about your new function find_min. Test
out your new function interactively within the interpreter, with some
input values of your choosing.
Now we want to reorganize exercise.py so that it does the same thing
as before, except more efficiently by using your new find_min
function.
Replace the appropriate blocks of code with new code that accomplishes
the same thing by calling your find_min function. Do not replace the
variables or change their values.
For example, one such operation will call find_min with the variables
x (with x having a value of 3) and y (with y having a value of 4) as
arguments and assign the returned value to the new variable min_xy.
Verify that your new code runs and produces the same results as the
original code.
My function definition is below.
def find_min(x, y):
if x < y:
return x
else:
return y
min_xy = find_min(3, 4)
print(min_xy)
I am getting the following errors:
Tests that failed:
! Call function find_min to find the lesser of x (x has a value of 3) and y (y has a value of 4) and assign returned value to min_xy
make sure x and y are defined create min_xy
! Call function find_min to find the lesser of a (a has a value of 12.3) and b (b has a value of 13.7) and assign returned value to min_ab
make sure a and b are defined create variable min_ab
! Call function find_min to find the lesser of w (w has a value of -3.9) and z (z has a value of -4.7) and assign returned value to min_wz
make sure w and z are defined create min_wz
Page 2 of 3
Instructions
The code editor should contain your find_min function. We are free to
define more than one function in our code. In the code editor, write a
second function called find_max that takes two inputs and returns the
greater of the two. Do Not Delete the Existing Code in the Code
Editor.
Use your new function to find the greater of x (x has a value of 3)
and y (y has a value of 4) and assign it to the variable max_xy.
Thanks in advance,
Marie
You need to take the call of the function out of the function definition.
def find_min(x, y):
if x < y:
return x
else:
return y
min_xy = find_min(3, 4)
print(min_xy)

Every python object has a type,id and a value?

Sometimes we define objects as a thing that contains type, id, and a value. Sometimes we say values themselves are objects. These two definitions contradict each other. For eg a=5 we can say there is an int object(a thing) that contains a value 5 and in the other circumstance, we say that 5 itself is an object(Hence in this case there is no such thing as a thing that contains the value 5). These 2 definitions do not conform to each other?? I am going through a python assignment and I was struggling on this for quite some time and I could not find a proper answer on this. Some authors were using the first definition and some are using the 2nd definition.
In python indeed everything is an object, including 5; you can display id(5) and type(5).
However for some objects the identity is irrelevant and you care about them only for the value. These objects must be immutable.
Number are this kind of objects... we don't care about this 5 or that 5; the very phrase doesn't sound logical. 5 is only interesting for its value.
For other objects (especially mutable ones) you instead care a lot about identity: this list is not that list, even if both are empty.
While using something like
if x is y: ...
would be a very bad idea in Python if x and y are number or strings, it would make perfectly sense if x and y are for example list instances.
The problem with number identity is that if x and y are numbers and I write:
z1 = x + y
z2 = x + y
may be z1 and z2 end up being the same object (i.e. id(z1) == id(z2) and z1 is z2 returns True) or may be not (i.e. id(z1) != id(z2) and z1 is z2 returns False).
For sure however the value of z1 and the value of z2 will be the same (i.e. z1 == z2) and that's what you care about when using numbers.

Default Parameters in Function Definition, Syntax problems.

I am having an issue finding a straightforward answer to a question that I have.
I am coding a program that has some default values for certain parameters that do not end up being called by the user. My program is somewhat complicated so I decided to try a simplified problem.
def mult(x = 1, y = 2, z = 3):
ans = x * y * z
print(ans)
mult()
In this quick program, the function call would result in 6. Which makes sense because it goes to the default values I provided. My question is, how can I call this function if, for example, I wanted to define y and not any other variable? What would be the correct syntax in that situation.
My intuition was to call mult(x, 5, z) to indicate default values for x and z but a new value for y. I know that does not work and would like to know what the correct syntax would be.
You can specify the parameter to supply by using = at the call site:
mult(y = 5)
you can call it with keywords
mult(y=7)
mult(z=55)
mult(z=12,y=16,x=5)
mult(x=15)
although as an aside its probably preferable to return ans instead of just printing it ...

Using Ranges and Multiplying

I have started creating a mini program, but I have 1 issue. I've created a variable, and I want to add something like this:
for x in range(0,12):
print (rand_no) * (x)
The variable rand_no is defined earlier in my program, but I want to multiply it by x. Please help me.
If you're using Python 3 as your tags indicate, you need to be aware that print is now a function. As a result, this code doesn't do what you're expecting:
for x in range(12):
# the call to `print` returns `None` and you try to multiply it by `x`
print(rand_no) * (x)
Instead, you want:
for x in range(12):
print(rand_no * x)

Optimizing Python polynomial evaluation

I have a function which evaluates terms of a polynomial in several variables. The inputs are lists of powers of each variable. For example, for two variables and 2nd order it looks like this,
def f(x,y):
return [1, x[1], y[1], x[1]*y[1], x[2], y[2]]
x = [2**0, 2**1, 2**2]
y = [3**0, 3**1, 3**2]
>>> f(x,y)
[1,2,3,6,4,9]
In reality the function is higher order and has many variables so on average there are a few thousand terms (in fact, I create the function at run time with an eval statement, but that's not important). The function is on an inner most loop and is currently a speed bottleneck. The profiler tells me I spend most of the time in __times__.
Short of creating a C extension module, can anyone see any room for optimization?
Edit: The example above is trying to evaulate 1 + x + y + xy + x^2 + y^2 with x = 2and y = 3, except without adding them, just putting each term in a list.
Adding them is fine (with some coefficients A, B, ...) i.e. all I'm trying to do is compute:
A + B*x + C*y + D*x*y + E*x^2 + F*y^2.
I'm not sure from which version, but numpy should have a polyval2d(x,y,c) function into the polynomial module, that will perfectly apply to your example.
You seemed interested in expanding your example to a much higher dimension.
In the same module there's a polyval3d(x,y,z,c), if that's not enought I'd suggest (as I guess you're already doing) to look at the source code. It shouldn't be too hard to implement what best suits your needs, and you can always ask here on SO :)
The function is on an inner most loop and is currently a speed
bottleneck.
You could try to get rid of the loop altogether, by using NumPy and replacing your variables with arrays of higher dimension.

Categories

Resources