random.choice shows the same answer if you use a variable - python

When I run this code, print(x) will print the same letter every time, and yet when I run it like the second example print(random.choice(b)) it works as expected. What is the difference? I checked for an answer a found references to "seeding", but I am not using random.seed() prior to this.
import random
b = "Hello World"
x = random.choice(b)
print(x)
print(x)
print(x)
# same answer as many times as you want to print
print(random.choice(b))
print(random.choice(b))
print(random.choice(b))
# random choice each time

By printing an assigned value 3 times will not change the value of the variable unless u call the random function to generate a new random variable again:)

random.choice(b) gets called only once when you assign the return value to x, it does not get called again each time you reference that variable. Each time you print x you are seeing the result of that initial assignment. When you do print(random.choice(b)) it is calling random.choice() on b each time. It would indeed be quite problematic if the value assigned to a variable changed each time you reference the variable.
There is really not much difference between what you are doing here:
x = random.choice(b)
print(x)
and what you are doing here:
print(random.choice(b))
The difference is that you do the latter 3 times (i.e., you call random.choice() 3x and print the result 3x), so you see 3 different results. If you do:
x = random.choice(b)
print(x)
x = random.choice(b)
print(x)
x = random.choice(b)
print(x)
You will see a different result each time (or at least a random result each time - it could be the same).

The difference is that the first one, x = random.choice(b) sets x to a random and then prints x, the letter that was randomly selected from b. It only randomly selects what x is when you declare x. The second, print(random.choice(b)) generates a new random every time.
You could use the following code to make x equal to random.choice:
b = "Hello world!"
x = random.choice
print(x(b))
And that does the same thing as print(random.choice(b)).

Related

How to repeat a function till its return value matches its previous return value?

I have a Python function that returns a value.
def population_gen(P)
...
return fittest
Now, I need to write a piece of code that compares the "fittest" with last iteration of the function call population_gen(P) that returned "fittest" and stops when the current fittest becomes equal to the previous one.
What I have tried is the following:
def population_gen(P)
...
return fittest
gen_count = 0
max_gen_count = 10
while gen_count <= max_gen_count:
population_gen(Pop)
gen_count += 1
I can run this any number of times (11 in this case) and make sure that my code is working. But, I do not want to it run 11 times, rather keep the while loop running till the aforementioned condition is met. I also wanted to mention that this function generates a population from a given initial population. Then, I feed this function again with the population that it generates and successfully keep it running for as many times I want. But I cannot implement the condition of comparing the "fittest" value.
Please help. Thanks in advance!
I assume that you want to keep iterating through the loop if the current and last values of the function returned is not equal.
Theory:
You can declare two variables, one inside loop and one outside. The work of inside one is to get the value of function returned by the function, and the outside one will be used to keep check of the previous value, so that it doesn't get lost (I mean the previous value here).
Now, you know, how simple it is, let's implement it. First, for the example, I would be creating a function that returns a random value from a list.
import random # Importing random module for help in choosing random value
def foo():
_list = [1, 2, 3]
return random.choice(_list)
Now, we have our example function, let's create a loop to keep check. NOTE: The type of loop you are using can be used, but the more efficient one is to use for loop, as you can use range function there as suggested by #Jab.
It's time to declare variables and the loop:
var = None # Outside the loop, will be used as a container for previous returned value
for _ in range(1, 12): # range(min. value, max. value [not included])
a = foo() # Creating a variable 'a', that would be holding current returned value from the function
if var is not None and a == var: # For first iteration, it would be None but the value will be assigned to 'var' in for it's next iteration and checking it whether the prev. and current values are equal or not
break # Break the loop
var = a # Assigns 'var' the value if the loop is still running
Now, the above example can be used as the answer. But, what if you want to check it? So, following is the code provided with the example for debugging purposes:
import random
def func():
l = [1, 2, 3]
val = random.choice(l)
print(val) # Printing the value, for debugging purposes
return val
var = None
for x in range(1, 12):
a = func()
if var is not None and a == var:
print(f'\nSame values after {x} iterations') # It will show, after how many iterations the loop stopped
break
var = a
Now, I ran the above code 3 times, the following is the output:
OUTPUT:
>>> 3
>>> 3
>>>
>>> Same values after 2 iterations
>>> 2
>>> 3
>>> 2
>>> 2
>>>
>>> Same values after 4 iterations
>>> 2
>>> 2
>>>
>>> Same values after 2 iterations
I hope you understood the concept.
Use a new default variable set as maximum in the arguments. Like -
def population_gen(P, prev_fit = 99999): if prev_fit < population_gen(P): return prev_fit
Assuming you want to call the function population_gen until it's last two invocations return the same value. The output of population_gen becomes the input in the next iteration.
import random
def population(limit: int) -> int:
return random.randint(1, limit)
prev = None
cur = population(10)
while prev != cur:
prev = cur
cur = population(prev)
print(prev)

python local variable- when do I have to assign a value?

I'm an amateur programmer and would like to seek advice while learning codes. Here I encounter some issues.
I found that when I remove the comment "#X=3" and make it into a code from the below then the code works. Without X=3, the code results into UnboundLocalError.
Browsed online, it's related to global and local variable but I can't see how it's related. And when does X has to be denoted before the while loop? and why "for y in primes" doesn't need to pre-define "y"?
Main purpose of the code: count the # of prime numbers up to (num)
def count_primes2(num):
primes = [2]
#x = 3
if num < 2:
return 0
while x <= num:
for y in primes: # use the primes list!
if x%y == 0:
x += 2
break
else:
primes.append(x)
x += 2
print(primes)
return len(primes)
As per design pattern variable should be created just before to use. In the code you are using x without creating or initializing default value.
"y" = you are iterating the list (primes). So in each iteration y will be initialized by the current value.So it will not give any error.
To expand, since you are using x in the while loop criteria, yes, it has to be defined before. You don't need to define y before the for loop because the for y in primes line defines y as each item in the list.
A rough translation to plain English:
while x <= num: == As long as this number is less than or equal to this other number, do the following
for y in primes == do the following for each item, named y, in primes
hopefully that wasn't more confusing
You need to create (and assign a value to) a variable before you use it. If you try to use a variable's value before creating the variable, then you get the exception. You do exactly this in the while expression: You ask if its value is below or equal to num, but it does not even exist yet, it has no value, this raises the exception.
Now, why do you get the UnboundLocalError?
The compiler goes through your code before the code gets executed. In this compile step it notices that you somewhere in your function assign a value to X, namely in the line x += 2. (There are even two of them.) This marks the variable for the compiler as a local variable.
So if you try to access the variable before the assignment takes place, the variable doesn't exist yet, but the code already knows that is supposed to be a local variable, hence the UnboundLocalError.
Without any assignment statement to X in the function you would have gotten a NameError because during execution of the while statement the interpreter then searches for a global variable of this name.

Python: multiplying 'for i in range(..) iteration'

So I have an assignment where I am required to return inf by multiplying x by 10 multiple times using a:
for i in range(...)
so the main part of my code is:
def g(x):
x = 10.*x
for i in range(308):
return x
and if I enter
>>> g(3.)
>>> 30.0
I expected it to iterate it 308 times to the point where I get inf. Is there a line I can use that uses the number in the for i in range(..) to iterate the equation that many times? For example:
def g(x):
x = 2.*x
for i in range(3):
# the mystery line I need for it to work
return x
>>> g(4.)
>>> 16.0
but it doesn't give me that. Rather it returns 8.0
Another way I did it that actually made it work was using print. But I don't think it's valid using a print statement in an assignment asking to return inf.
I think you have the right parts, just not arranged correctly. Try something like this:
def g(x):
for i in range(308):
x = 10.*x # because we've moved this line into the loop, it gets run 308 times
return x # since we've unindented this line, it runs only once (after the loop ends)
The part you want to be repeated needs to be indented after the line with the for statement. Stuff you don't want repeated (like the return, which can only happen once), should not be in the loop.
The reason it isn't iterating like you expect is because of the return statement. return exits from whatever procedure/function that you are running immediately and returns the value given to it. Here is a walk through of your first function, assuming it was called with the value of 4 as in g(4.).
# the start of the function
# x = 10
# this line sets x = 100. I think you can see why.
x = 10. * x
# this sets i = 0 and begins to loop
for i in range(308):
# this IMMEDIATELY returns from the function with the value
# of x. At this point, x = 100. It does not continue looping!
# Without this line, i would be set to 1, 2, 3, ..., 307 as
# you loop through the range. This is why it worked with print.
return x
What you want instead of this is something that will accumulate the value of the repeated multiplications. You don't want to return anything at all within the loop, assuming you want every iteration to run. I will not give you the exact answer because this is homework but I will give a hint. You probably do not want return to be indented, as it is in the second bit of code you provided. You probably want something more like this:
def g(x):
x = 2 * x
for i in range(3):
# { your code here }
# You want to accumulate the value!
return x

Python: Unexpected print values from within a simple function

I have created an simple, arbritrary function that prints out a value (1) based on what the first element from a randomly shuffled list is.
Looking at the code below: I am creating a variable and setting it to 1, then I'm a creating a small list (1,2,3) and then shuffling the list. The idea is, if the first element of that list (after shuffle) is 1 or 2, then print the value of 'correct', BUT if the first element of the list happens to be 3, set 'correct' to 0, and then run the function again. As you can see from the if statement, when 'value' is set to 0, I don't expect this to be printed at all because the function is being run again (chair()) before any printing takes place.
Having run this, I expected to find a print out of 5 values of 1. The problem is, I am seeing 0 values printed too. This seems like a very simple function, and I feel a little but stupid for not seeing why this is happenig. Any ideas?
def chair():
correct = 1
a = [1,2,3]
random.shuffle(a)
if a[0] == 3:
correct = 0
chair() #run function again without printing
print correct
for i in range(5):
chair()
Just calling chair() does not modify correct. You need to do correct = chair(). The problem with that is chair() does not return anything; it prints it. You should move the printing to outside of the function and return instead:
def chair():
correct = 1
a = [1,2,3]
random.shuffle(a)
if a[0] == 3:
correct = chair()
return correct
for i in range(5):
print chair()
Your function is recursive, so when you recall the function again to avoid printing, the function will still finish. If you added an else statement, you'd see those zeros disappear. Ex:
def chair():
correct = 1
a = [1,2,3]
random.shuffle(a)
if a[0] == 3:
correct = 0
chair() #run function again without printing
else:
print correct
for i in range(5):
chair()
edit: grammar
edit: example

variable doesn't reset in while loop with function

I have never come across this before and wonder if anyone has a solution. I have a while loop with a function inside that returns an integer. The function takes a string and a list. The first iteration of the while loop returns the correct answer but on subsequent iterations the list seems to be empty even though the function does not change the list in any way. Also if i try to reset the list after the function in the while loop the new list also seems to be empty. It seems to be very strange behavior. Any explanation as to whats going on would be much appreciated. The code of the function inside the loop is quite long so at this stage I will avoid posting it. However if requested then I will post.
spectrum = [1,2,3,4,5,6]
leaderboard = ['zzz','xxx','yyy']
pep_scores = []
j=0
original_spectrum = spectrum
print len(original_spectrum)
while j < len(leaderboard):
x= linear_score(leaderboard[j],spectrum) #this function doesn't alter spectrum
print leaderboard[j], x
spectrum = original_spectrum #should reset spectrum even though it shouldn't be necessary to do that
print len(spectrum), len(original_spectrum) #prints 2 empty lists
pep_scores.append(x) #appends correct score on 1st iteration and '0' for all others
j=j+1
I had added print statements to try to resolve the problem, my original code did not contain 'original_spectrum = spectrum' or 'spectrum = original_spectrum' in the while loop. I don't understand why after 1 iteration 'origninal_spectrum' is an empty list. I haven't posted the function because I cannot see how it could be causing the problem. Please ask if you need more information.
To create copy of the list use copy_list = original_list[:].
So in your example:
spectrum = [1,2,3,4,5,6]
leaderboard = ['zzz','xxx','yyy']
pep_scores = []
j=0
original_spectrum = spectrum[:]
print len(original_spectrum)
while j < len(leaderboard):
x= linear_score(leaderboard[j],spectrum) #this function doesn't alter spectrum
print leaderboard[j], x
spectrum = original_spectrum[:] #should reset spectrum even though it shouldn't be necessary to do that
print len(spectrum), len(original_spectrum) #prints 2 empty lists
pep_scores.append(x) #appends correct score on 1st iteration and '0' for all others
j=j+1
Its because of that you define spectrum outside the function and its scope is global , and when you pass spectrum to your function as its the name of list any changes on it change it globally not local in your function ! and note that its just about mutable (like lists) objects . (Note : labels are pointer to special memory addresses ) (your copy command original_spectrum = spectrum just make 2 label for one object !!! )
for better understanding see the below example :
>>> a=[1,2,3]
>>> def f(s):
... s.remove(1)
...
>>> f(a)
>>> a
[2, 3]
>>> def f(s):
... s+=[1,2]
...
>>> f(a)
>>> a
[2, 3, 1, 2]
Now you have 2 choice :
make a copy of spectrum and pass that to function :
copy_spectrum = spectrum[:]
define spectrum inside the function and one outside for global usage !

Categories

Resources