How incrementor function is not incrementing the num variable? - python

I am unable to understand please help me with same. I just want to know why num variable is not incrementing on calling a function incrementor? i guess output should be (100,100), Instead it is showing (100,0)
def main():
counter=Counter()
num=0
for x in range(0,100):
incrementor(counter,num)
return (counter.count, num)
def incrementor(c, num):
c.count+=1
num+=1
class Counter:
def __init__(self):
self.count=0
print(main())

When you have code like this:
class Counter:
def __init__(self):
self.count = 0
def incrementor(c, num):
c.count += 1
num += 1
def main():
counter = Counter()
num = 0
incrementor(counter, num)
return (counter.count, num)
print(main())
What is actually happening at the call site: incrementor(counter, num) is this:
WARNING: PSEUDO CODE AHEAD
counter = Counter()
num = 0
c = counter
num = num
call incrementor
The above is bizarre and easy to misunderstand, so I'll rephrase it:
WARNING: PSEUDO CODE AHEAD
def incrementor(c, n):
c.count += 1
n += 1
counter = Counter()
num = 0
c = counter
n = num
call incrementor
Now where I have put n = num the n is the name of the variable used inside incrementor(), which shows n is a different variable, which gets incremented inside the function, but thrown away when it returns.
So, in order to do what it seems you want to do you need to do this:
class Counter:
def __init__(self):
self.count = 0
def incrementor(c, num):
c.count += 1
return num + 1
def main():
counter = Counter()
num = 0
for x in range(0, 100):
num = incrementor(counter, num)
return (counter.count, num)
print(main())
Output:
(100, 100)

Related

how to complete id numbers generator code in python

Hi there I have a mission: to implement 10 ID numbers according to the exceptions and conditions in the code
i want that the output will be
123456782
123456790
123456808
123456816
123456824
123456832
123456840
123456857
123456865
123456873
and somehow i Can't reach the desired output, anyone can help? :)
import string
letters = string.ascii_letters
digits = string.digits
class NumNotNineLong(Exception):
def __init__(self):
pass
def __str__(self):
return "The number you provided is not nine digits long."
class NotNumber(Exception):
def __init__(self):
pass
def __str__(self):
return "The input you provided is not an integer"
class IDIterator():
increment = 1
def __init__(self,_id):
self._id = _id
def __iter__(self):
return self
def __next__(self):
while check_id_valid(str(self._id)[-9::]) == False:
self._id *= 2
self._id += IDIterator.increment
IDIterator.increment += 1
if check_id_valid(str(self._id)[-9::]):
result = str(self._id)[-9::]
self._id *= 2
self._id += 1
IDIterator.increment = 2
return result
def check_id_valid(id_number):
for letter in str(id_number):
if letter not in string.digits:
raise NotNumber
numbers = [int(i) for i in str(id_number)]
if len(numbers) != 9:
raise NumNotNineLong
set_numbers = []
for i in range(len(numbers)):
if i % 2 == 0:
set_numbers.append(numbers[i])
else:
set_numbers.append(numbers[i] * 2)
true_numbers = []
for num in set_numbers:
if num > 9:
temp = [int(i) for i in str(num)]
true_numbers.append(sum(temp))
else:
true_numbers.append(num)
if sum(true_numbers) % 10 == 0:
return True
else:
return False
def main():
result = IDIterator(123456780)
for _ in range(10):
print(result.__next__())
if __name__ == "__main__":
main()

local variable 'n' referenced before assignment. Closures

def fibonacci_closure(n):
def fibonaci():
if n == 0: """in this line error occured idk why because in watches i see n=4"""
return 0
elif n == 1 or n == 2:
return 1
else:
i = 1
j = 1
tmp = 1
while n != 2:
n -=1
tmp = i
i = j + i
j = tmp
return i
return fibonaci
a = fibonacci_closure(4)
a()
Task:
Return a closure that will generate elements of the Fibonacci sequence when called repeatedly.
Example:
g = fibonacci_closure()
g() # 1
g() # 1
g() # 2
g() # 3
UnboundLocalError: local variable 'n' referenced before assignment
Fibonacci numbers are a typical example for generators. It's only irritating why the function should return a function instead of a generator.
def fibonacci_closure():
def fibonacci():
i = j = 1
while True:
yield i
i, j = j, i + j
return fibonacci().__next__
The task you are trying to accomplish could be done by creating a class. (Or you could look into creating a 'generator' object, which is its own separate thing.)
What you need in order to preserve the value of n from one call to the next is some sort of global variable. Global variables in Python are possible, but are bad practice. The same thing can be accomplished from within a class where n is stored and encapsulated within that class.
Have a look at the changes I made and see if the function now works as you intended. Cheers!
class fibonacci_closure():
def __init__(self):
self.n = 0
def fibonaci(self):
if self.n == 0:
self.n+=1
print(0)
elif self.n == 1 or self.n == 2:
self.n+=1
print(1)
else:
i = 1
j = 1
tmp = 1
hold = self.n
while hold != 2:
hold -=1
tmp = i
i = j + i
j = tmp
self.n+=1
print(i)

I.D number generator

so basically i got an assignment to create a generator that will produce valid I.D numbers for citizans in my country.
a valid number is 9 digits, for each digit you need to multiply it by 1 or 2 according to the index, if the index is even, multiply the num by 1, else multiply it by 2.
after that if a curtain digit became greater than 9, change it to the sum of its digits.
if the overall sum % 10 == 0 then the num is valid.
else false.
after that they wanted me to create a class that will produce an itirator.
in the next method:
if the number that was given is valid, return it and multiply afterwards by 2 and add 1, and then check again if valid or not, if not multiply by 2 and add 2 and so on..
if from the beginning the num wasn't valid, multiply by 2 and add 1 then multiply by 2 and add 2 and so on...
import string
letters = string.ascii_letters
digits = string.digits
class NumNotNineLong(Exception):
def __init__(self):
pass
def __str__(self):
return "The number you provided is not nine digits long."
class NotNumber(Exception):
def __init__(self):
pass
def __str__(self):
return "The input you provided is not an integer"
class IDIterator():
increment = 1
def __init__(self,_id):
self._id = _id
def __iter__(self):
return self
def __next__(self):
while check_id_valid(str(self._id)[-9::]) == False:
self._id *= 2
self._id += IDIterator.increment
IDIterator.increment += 1
if check_id_valid(str(self._id)[-9::]):
result = str(self._id)[-9::]
self._id *= 2
self._id += 1
IDIterator.increment = 2
return result
def check_id_valid(id_number):
for letter in str(id_number):
if letter not in string.digits:
raise NotNumber
numbers = [int(i) for i in str(id_number)]
if len(numbers) != 9:
raise NumNotNineLong
set_numbers = []
for i in range(len(numbers)):
if i % 2 == 0:
set_numbers.append(numbers[i])
else:
set_numbers.append(numbers[i] * 2)
true_numbers = []
for num in set_numbers:
if num > 9:
temp = [int(i) for i in str(num)]
true_numbers.append(sum(temp))
else:
true_numbers.append(num)
if sum(true_numbers) % 10 == 0:
return True
else:
return False
def main():
result = IDIterator(123456780)
for _ in range(10):
print(result.__next__())
if __name__ == "__main__":
main()
my results are :
209872373
274495985
097983944
391935780
903409134
227273083
545477432
363819467
910555747
409086964
wanted results are:
209872373
863664504
569826803
339640302
473959864
544578024
356624288
466187762
040830960
487293938
save me
thank you!
My take on the problem:
class IDIterator:
def __init__(self, num):
self.__num = num
def __iter__(self):
n, num = 1, self.__num
while True:
num = int( str(num)[-9:] )
if is_valid(num):
yield '{:0>9}'.format(num)
num *= 2
num += n
n = 1
else:
num *= 2
num += n
n += 1
def is_valid(num):
s = '{:0>9}'.format(num)
if len(s) != 9:
return False
nums = [int(ch) * 2 if i % 2 else int(ch) for i, ch in enumerate(s)]
nums = [sum(int(c) for c in str(n)) for n in nums]
return sum(nums) % 10 == 0
from itertools import islice
for num in islice(IDIterator(123456780), 0, 10):
print(num)
Prints:
209872373
863664504
569826803
339640302
473959864
544578024
356624288
466187762
040830960
487293938

Keep getting type error with decorative function

I keep getting a type error for this. I am experimenting with decorative functions. Any help is appreciated
def primer(func):
def primes(n):
print (n)
return None
#primer
def find_prime(n):
while True:
count = 2
if (count == n):
z = ("PRIME")
return z
elif (n % count == 0):
z = n / count
return z
else:
count += 1
continue
prime = find_prime()
prime(10)
def primer(func):
def primes(n):
print(n)
#return None: dont know why this is here, you could do without it
return primes
#The nontype error is occuring because your code is returning none
#so to fix that all you have to do is return the inner function
#primer
def find_prime(n):
while True:
count = 2
if (count == n):
z = ("PRIME")
return z
elif (n % count == 0):
z = n / count
return z
else:
count += 1
continue
prime = find_prime
# if you want to turn a function into a variable you have to make sure it's
# callable, which means no parantheses around it
prime(15) # then you can call it

Why is the code (Python) giving error?

import numpy as np
import matplotlib.pyplot as plt
class Prisoners_Dilemma:
def __init__(self,n,p):
self.n = n
self.p = p
def decision_array(self):
self.dict_dict = {}
for i in range(1,self.n + 1):
self.dict_dict[i] = []
list_list = []
for j in range(1,self.n):
#np.random.seed(j)
self.r = np.random.uniform(0,1)
if self.r > self.p:
q = 0
else:
q = 1
list_list.append(q)
self.dict_dict[i] = list_list
return self.dict_dict
def payoff(self):
self.dict_dict_2 = {}
for i in range(1,self.n + 1):
self.dict_dict_2[i] = []
list_list_2 = []
list_list_3=[]
for j in range(1, i):
list_list_2.append(self.dict_dict[j][i-2])
for j in range(i + 1, self.n + 1):
list_list_2.append(self.dict_dict[j][i-1])
list_list_2_np = np.array(list_list_2)
against_i = np.sum(list_list_2_np)
for_i = np.sum(self.dict_dict[i])
if against_i == 0 and for_i == 0:
payoff_i = 2
elif against_i == 0 and for_i != 0:
payoff_i = 5
elif against_i != 0 and for_i == 0:
payoff_i = -5
else:
payoff_i = -2
list_list_3.append(payoff_i)
self.dict_dict_2[i]=list_list_3
return self.dict_dict_2
def gameplay(self, N, initial_count):
self.counter = initial_count
for i in range(N):
for j in range(1, self.n + 1):
z = self.dict_dict_2[j]
x = np.array(z)
self.counter += np.sum(z)
return self.counter
y = Prisoners_Dilemma(15,0.015)
print (y.gameplay(20,100))
In the above code, the compiler gives the error that instance has no attribute as dict_dict_2 even though its prefixed with self. Moreover, it is perfectly fine with dict_dict. For the sake of completeness I have included the whole code but the problem lies only in payoff and gameplay methods?
dict_dict_2 is only created in payoff(), therefore you must call it before attempting to call gameplay().
The issue is that you are only creating self.dict_dict_2 variable in the payoff function, but in your logic where you are calling gameplay() function , you are not calling the payoff() function before accessing dict_dict_2 , from the looks of it you are not calling that function anywhere at all.
Not sure what dict_dict_2 holds, but the above is the reason why you are getting the issue, maybe you can move the initialization part of dict_dict_2 to __init__() function , though that would not fix the complete issue, since you would still be trying to access dict_dict_1[j] which can error out if j is not a key in dict_dict_2 .

Categories