How can I ensure that a function is "defined" in Python? - python

Trying to learn python as a java programmer. I would really appreciate some insight into why my program is telling me that my "isPrime" function isn't defined, especially with the use of 'self.'
import math
class Problem10:
def sumOfPrimesX(self, number):
sum = 0
for i in range(0, number):
if isPrime(i):
sum += i
return sum
def isPrime(self, x):
for n in range(0, math.floor(x/2)):
if x % n == 0:
return False
return True
print(sumOfPrimesX(input()))

all functions need it as their first parameter in a python program
No, only the instance methods, the methods related to a specific instance of a class. A simple function can need to parameter.
And you won't see the parameter self filled with the classic way of calling it, if you call the method on a instance it'll be filled by it
p = Problem10()
p.sumOfPrimesX(int(input("Give a value"))) # call on instance, one paramater given
# same as
Problem10.sumOfPrimesX(Problem10(), int(input("Give a value")))
# call on class itself, need to pass an instance as first to fill 'self
Also you need to wrap the input in an int, also start the loop at 2
p = Problem10()
print(p.sumOfPrimesX(int(input("Give a value"))))
class Problem10:
def isPrime(self, x):
for n in range(2, math.floor(x / 2)):
if x % n == 0:
return False
return True

The issue is both isPrime and sumofPrimesX are methods of the class Problem10.
Try the following:
import math
class Problem10:
def sumOfPrimesX(self, number):
sum = 0
for i in range(0, number):
if self.isPrime(i):
sum += i
return sum
def isPrime(self, x):
for n in range(0, math.floor(x/2)):
if x % n == 0:
return False
return True
pv = Problem10()
print(pv.sumOfPrimesX(input()))

Related

What is the problem in this code? i get an Error in this code [duplicate]

I am coding a program in python. I introduce an entire number and the program gives back to me the decomposition in prime factors of this number.
For example 6 ---> 3, 2. Another example 16 --> 2, 2, 2, 2.
I am doing it with OOP. I have created a class (PrimeFactors) with 2 methods (is_prime and prime_factor_decomposition). The first method says wether the number is prime, and the second gives the decomposition back.
This is the code:
class PrimeFactors(object):
def __init__(self, number):
self.number = number
def is_prime(self):
n = self.number - 1
a = 0
loop = True
if self.number == 1 or self.number == 2:
loop = False
while n >= 2 and loop:
if self.number % n != 0:
n -= 1
else:
a += 1
loop = False
return a == 0
def prime_factor_decomposition(self):
factors = []
n = self.number - 1
loop = True
if PrimeFactors.is_prime(self.number):
factors.append(self.number)
loop = False
while n >= 2 and loop:
if self.number % n == 0 and PrimeFactors.is_prime(n):
factors.append(n)
self.number = self.number / n
if self.number % n == 0:
n += 1
n -= 1
return factors
s = PrimeFactors(37)
print(s.is_prime())
I am getting a mistake. I think it is something related to the method call.
My question is, How can I call a method from another method if they both are from the same class?
You need to use self. to call another method of the same class:
class Foo:
def __init__(self):
pass
def method1(self):
print('Method 1')
def method2(self):
print('Method 2')
self.method1()
Jkdc's answer is absolutely correct. I also wanted to note that your method calls are going to be problematic. You defined is_prime to take self as its only argument, but when you call it, you're passing in self.number or n.
If you need is_prime to work with arbitrary numbers, and not just whatever the class was initialized with, you should add an extra argument.
Just a general advise: there are good (and FAST!) algorithms to check if a number is prime. your loop starts with n-1, thats highly inefficient. lets say the number is
1000000, so your algorithm starts with 999999, but the first even POSSIBLE number is the half of n! so instead i would go from 2 up to n/2:
for i in range(n/2):
if self.number%i==0:
return true
return false
i think even better for your purpose is to return not a boolean, but the number, which is found to be the divisor:
for i in range(n/2):
if self.number%i==0:
return i
return 0
then you can repeatedly call the method and will only get the prime numbers.

How to continue calling __init__ funtion until certain condition meet?

Take the below code for an example.
import random
class test:
def __init__(self):
x = random.choice([1,2,3])
print(x)
if x == 2:
pass
What I want to do here is that when x equals 2 then run the function again and get the different value of x. Therefore whenever I call the test class it always assigns the x value other than 2.
NOTE: We must run the random.choice() in the __init__ and always get the value other than 2, it's okay to run the __init__ as many times as we want unless we get the different value.
The value of x is random.
What I have tried
class test:
def __init__(self):
x = random.choice([1,2,3])
if x != 2:
self.x = x
else:
test()
Update:
Implementing the while loop sounds a good idea.
Try this:
import random
class test:
def __init__(self):
x = random.choice([1,2,3])
loop = 0
while x == 2:
x = random.choice([1,2,3])
loop += 1
if loop >= 5:
x = False
It is impossible to return any value from the __init__() function, since the function is supposed to return None, therefore I have set the x value to False, if it is something you'd like,
You really don't want to be calling init recursively. If you're using Python 3.8+ there's a neat way to fulfil your requirement.
class test:
def __init__(self):
while (x := random.choice([1,2,3])) == 2:
pass
At some point the while loop will terminate when x is either 1 or 3

How to alter the value of variable with a function?

How to alter the value of a variable with a function and store it permanently.
tried the code below but it doesn't alter the value of variable.
n=2
def f(x):
x+=2
return x
f(n)
print n #the output is 2 instead of 4 I want
Think of variable as labels to values, n is labeling 2, if you want n to label the value of the f function just label it again:
n=2
def f(x):
x+=2
return x
n = f(n)
print n
def f(x):
return x + 2
n = 2
n = f(n)
print(n)
This is how functions should be used. They receive values as arguments and return new values. When/where/how that is assigned to a variable is the caller's problem, since the variable is in the caller's scope.
If you want "self modification", a class is probably the better option:
class Foo:
def __init__(self, n):
self.n = n
def inc(self):
self.n += 2
f = Foo(2)
f.inc()
print(f.n)

if Python doesn't support method overloading, then why does this method overload work while this other does not?

If Python does not support method overloading (besides *args and **kwargs or PEP 3124), then why does this overload work?
# the sum from 1 to n
def sum(n):
if n > 0:
return n + sum(n - 1)
else:
return 0
print(sum(3))
# the sum from n to m, inclusive
def sum(n, m):
if n <= m:
return n + sum(n + 1, m)
else:
return 0
print(sum(3,5))
... while more baffling, this one does not:
# the sum of elements in an array
def sumArray(A):
return sumArray(A, len(A)-1)
# a helper for the above
def sumArray(A, i):
if i < 0:
return 0
else:
return A[i] + sumArray(A, i-1)
print(sumArray([1,2,3]))
You aren't overloading. You're hiding one thing behind another by using the same name for different objects. Try
sum = 42
and see how print(sum(3, 5)) ceases to work.
Function definitions are variable assignments. They create a function and assign it to the variable matching the name you used. You're seeing the ordinary effects of reassigning a variable.
def sum(n):
...
This assigns a function of 1 argument to the variable sum.
print(sum(3))
This uses the function assigned to that variable.
def sum(n, m):
...
This assigns a new function to the variable sum, replacing the first function.
print(sum(3,5))
This uses the new function. If you had tried to use the old function, you wouldn't find it.
# the sum of elements in an array
def sumArray(A):
return sumArray(A, len(A)-1)
# a helper for the above
def sumArray(A, i):
if i < 0:
return 0
else:
return A[i] + sumArray(A, i-1)
print(sumArray([1,2,3]))
This assigns a function to sumArray, then assigns a different function to sumArray, then tries to use the value from the first assignment. It finds the second function, and fails.
In your first example, you define function and use it, then overwrite it with another, and use the new one, just like with regular variables:
a = 1
print(a)
a = 2
print(a)

How do I call a method from another method?

I am coding a program in python. I introduce an entire number and the program gives back to me the decomposition in prime factors of this number.
For example 6 ---> 3, 2. Another example 16 --> 2, 2, 2, 2.
I am doing it with OOP. I have created a class (PrimeFactors) with 2 methods (is_prime and prime_factor_decomposition). The first method says wether the number is prime, and the second gives the decomposition back.
This is the code:
class PrimeFactors(object):
def __init__(self, number):
self.number = number
def is_prime(self):
n = self.number - 1
a = 0
loop = True
if self.number == 1 or self.number == 2:
loop = False
while n >= 2 and loop:
if self.number % n != 0:
n -= 1
else:
a += 1
loop = False
return a == 0
def prime_factor_decomposition(self):
factors = []
n = self.number - 1
loop = True
if PrimeFactors.is_prime(self.number):
factors.append(self.number)
loop = False
while n >= 2 and loop:
if self.number % n == 0 and PrimeFactors.is_prime(n):
factors.append(n)
self.number = self.number / n
if self.number % n == 0:
n += 1
n -= 1
return factors
s = PrimeFactors(37)
print(s.is_prime())
I am getting a mistake. I think it is something related to the method call.
My question is, How can I call a method from another method if they both are from the same class?
You need to use self. to call another method of the same class:
class Foo:
def __init__(self):
pass
def method1(self):
print('Method 1')
def method2(self):
print('Method 2')
self.method1()
Jkdc's answer is absolutely correct. I also wanted to note that your method calls are going to be problematic. You defined is_prime to take self as its only argument, but when you call it, you're passing in self.number or n.
If you need is_prime to work with arbitrary numbers, and not just whatever the class was initialized with, you should add an extra argument.
Just a general advise: there are good (and FAST!) algorithms to check if a number is prime. your loop starts with n-1, thats highly inefficient. lets say the number is
1000000, so your algorithm starts with 999999, but the first even POSSIBLE number is the half of n! so instead i would go from 2 up to n/2:
for i in range(n/2):
if self.number%i==0:
return true
return false
i think even better for your purpose is to return not a boolean, but the number, which is found to be the divisor:
for i in range(n/2):
if self.number%i==0:
return i
return 0
then you can repeatedly call the method and will only get the prime numbers.

Categories