How to fix this OOP error? - python

I am trying to understand python oop. but it's not easy for me. thus i wrote
python OOP program (ex.2) for below procedural program (ex.1) but It's not working with below error.
ex.1
def factorial(n):
num = 1
while n >= 1:
num = num * n
n = n - 1
return num
f = factorial(3)
print f # 6
ex.2
class factorial:
def __init__(self):
self.num = 1
def fact(self,n):
while n>=1:
num = self.num * n
n = n-1
return num
f = factorial()
ne= factorial.fact(3)
print(ne)
error
Traceback (most recent call last):
File "F:/python test/oop test3.py", line 13, in ne= factorial.fact(3)
TypeError: fact() missing 1 required positional argument: 'n'

use the instance you created to call the method:
f = factorial() # creates instance of the factorial class
ne = f.fact(3)
Or to call using the class itself without assignment:
ne = factorial().fact(3) # < parens ()
print(ne)
You also have a mistake you should be using self.num or you will always get 1 as the answer, so:
class Factorial: # uppercase
def __init__(self):
self.num = 1
def fact(self, n):
while n >= 1:
self.num = self.num * n # change the attribute self.num
n -= 1 # same as n = n - 1
return self.num
If you don't return your method will return None but you will still increment self.num so if you don't want to return but want to see the value of self.num after you call the method you can access the attribute directly:
class Factorial:
def __init__(self):
self.num = 1
def fact(self, n):
while n >= 1:
self.num = self.num * n
n -= 1
ne = Factorial()
ne.fact(5) # will update self.num but won't return it this time
print(ne.num) # access the attribute to see it

There are three problems:
1) Logical error: num = self.num * n should be changed
to self.num = self.num * n, Here num is another variable which you are creating.
2) Logical error, But If 1st one is addressed it becomes Syntax error:
return num should be changed to return self.num
3) Syntax Error:
f = factorial()
ne= factorial.fact(3)
should be either changed to
ne = factorial().fact(3) or ne = f.fact(3)

Related

Program entering an infinite loop

I am new to programming so this might come off as a silly question but can you help me with this code..... I am trying to print just the first ten numbers after the number 'self.num' but somehow it is just entering an infinite loop which I am having to terminate
class TopTen:
def __init__(self, num):
self.num = num
def __iter__(self):
return self
def __next__(self):
if self.num <= self.num+10:
val= self.num
self.num += 1
return val
else:
raise StopIteration
values = TopTen(5)
for i in values:
print(i)
You can implement it like this:
class TopTen:
def __init__(self, num):
self.num = num
self.maxNum = num+10
def __iter__(self):
return self
def next(self):
if self.num < self.maxNum:
val = self.num
self.num += 1
return val
else:
raise StopIteration
for i in TopTen(5):
print(i)
# Prints
# 5
# 6
# 7
# 8
# 9
# 10
# 11
# 12
# 13
# 14
The reason why you have infinite loop is because if self.num <= self.num + 10: will always evaluate to True, as you increase self.num by 1 each time by calling next(), so self.num + 10 will always be higher than self.num.
The condition test if self.num <= self.num+10: in your class will always be true, thats the reason for the infinite loop:

GCD implementation of fraction addition not working properly

I am following the Runestone Academy Python3 course and tried to implement 'addition' feature for fractions using Class but I am getting error.
When I am not using GCD implementation, the code is running fine
Here is my code:
class Fraction:
def __init__(self, top, bottom):
self.num = top
self.den = bottom
def show(self):
print(f'{self.num}/{self.den}')
def __str__(self):
return f'{self.num}/{self.den}'
# adding without GCD implementation
# def __add__(self,other_fraction):
# new_num = self.num * other_fraction.den + self.den * other_fraction.num
# new_den = self.den * other_fraction.den
# return Fraction(new_num, new_den)
# adding with GCD implementation
def gcd(self, m, n):
while m % n != 0:
m, n = n, m % n
return n
def __add__(self, other_fraction):
new_num = self.num * other_fraction.den + self.den * other_fraction.num
new_den = self.den * other_fraction.den
common = gcd(new_num, new_den)
return Fraction(new_num // common, new_den // common)
# my attempt of adding two fractions by creating a method 'add'
# def add(self,other_fraction):
# new_num = self.num * other_fraction.den + self.den * other_fraction.num
# new_den = self.den * other_fraction.den
# return Fraction(new_num, new_den)
# my_fraction = Fraction(3,5)
# print(my_fraction)
# print(f'I ate {my_fraction} of my pizza')
# my_fraction.__str__()
# str(my_fraction)
f1 = Fraction(1, 4)
f2 = Fraction(1, 2)
f3 = f1 + f2
# f3 = f1.add(f2)
print(f3)
This is the error I am getting:
Traceback (most recent call last):
File "D:/Python/Mosh_Lec/app.py", line 74, in <module>
f3 = f1 + f2
File "D:/Python/Mosh_Lec/app.py", line 53, in __add__
common = gcd(new_num, new_den)
NameError: name 'gcd' is not defined
I also tried with this variation but same error:
def gcd(self, m, n):
self.num = m
self.den = n
while self.num % self.den != 0:
self.num, self.den = self.den, self.num % self.den
return self.den
The gcd method should not logically be part of the Fraction class. Indeed, you can call the gcd method with any two numbers, they do not need to be the numerator and denominator of a fraction. Therefore I would move the gcd function outside of the class.
def gcd(m, n):
...
class Fraction:
...
Look at there:
NameError: name 'gcd' is not defined
It means that it cannot find the function(or method) named gcd. Of course! It need to be called with a Fraction object, so try to change your source code at line 32:
- common = gcd(new_num, new_den)
+ common = self.gcd(new_num, new_den)
self is a Fraction object.
By the way, the method gcd that do not use the parament self should be defined as a static function:
class Fraction:
...
#staticmethod
def _gcd(m: int, n: int):
...
...
And call the method by Fraction._gcd (the underline means that it is private function(or method)).
See it's a simple issue if u see the error:
File "D:/Python/Mosh_Lec/app.py", line 53, in __add__
common = gcd(new_num, new_den)
NameError: name 'gcd' is not defined
you will see that you have defined gcd but why it is saying GCD, not defined here's the reason:
common = self.gcd(new_num, new_den)
It is as simple as that just put the above code like this:
def __add__(self, other_fraction):
new_num = self.num * other_fraction.den + self.den * other_fraction.num
new_den = self.den * other_fraction.den
common = self.gcd(new_num, new_den)
return Fraction(new_num // common, new_den // common)
and your problem is solved! Kudos!
It as simple as that.......

Dynamic Array Type Error on making the list function

New to data structures and Algorithms trying out Dynamic Arrays
import ctypes
class DynamicArray(object):
def __init__(self):
self.count = 0
self.capacity = 1
self.A = self.make_array(self.capacity)
def __len__(self):
return self.count
def get(self, x):
if not 0 <= x < self.count:
return IndexError(f'Your value is {x} is out of bounds ')
return self.A[x]
def append(self, x):
if self.count == self.capacity:
self._resize(2 * self.capacity)
self.A[self.count] = x
self.count += 1
def _resize(self, new_cap):
B = self.make_array(new_cap)
for i in range(self.count):
B[x] = self.A[x]
self.A = B
self.capacity = new_cap
def make_array(self):
return (new_cap * ctypes.py_objects)()
arr = DynamicArray()
arr.append(1)
When I test run the code I get the error that
ln8: self.A = sekf.make_array(self.capacity) TypeError: make_array()
takes in 1 positional arguments and 2 were given
I do not understand because I only passed in one argument unless I am not understanding please help
On the function
def make_array(self, new_cap):
return (new_cap * ctypes.py_objects)()
The argument 'new_cap' was missing hence throwing the 1 argument error

How to call a python class like calling a function

Searching to build up my personal style of programming i want to be able to call a python class the same way i'd call a python function.
Here's what i mean:
consider this function:
def Factorial(n):
if n == 0:
return 1
else:
return n * Factorial(n - 1)
This is a function that outputs 24 when you call Factorial(4).
Now let's consider a class instead:
class Factorial:
def __call__(n):
if n == 0:
return 1
else:
return n * Factorial()(n - 1)
This code works the same way as the previous code except at call time where you instead write:
Factorial()(4) # which outputs 24
Now my question is how could you do this instead:
Factorial(4) # just that, and output 24, from THE object.
Thanks!
Use self.
class Factorial:
def __call__(self, n):
if n == 0:
return 1
else:
return n * self(n - 1)
f = Factorial()
f(3)
# 6
f(5)
# 120
From there you can easily add a starting value in your __new__ constructor.
class Factorial:
def __new__(cls, value=None):
instance = super().__new__(cls)
if value is None:
return instance
else:
return instance(value)
def __call__(self, n):
if n == 0:
return 1
else:
return n * self(n - 1)
Now you can
Factorial(5)
# 120
f = Factorial()
f(5)
# 120
Use a constructor (which is __init__ in Python) like so:
class Factorial:
def __init__(self, n):
// code here
You can override __new__ method:
class Factorial:
def __new__(cls, n):
if n == 0:
return 1
else:
return n * Factorial(n - 1)
Although the above solution works, I prefer a decorator-based solution which is less magical and is more intuitive and explicit:
def function_factory(cls):
return cls()
#function_factory
class Factorial:
def __call__(self, n):
if n == 0:
return 1
else:
return n * Factorial(n - 1)
A short & simple change in your existing code:
>>> class Factorial:
... def __call__(self,n):
... if n == 0:
... return 1
... else:
... return n * self.__call__(n - 1)
...
>>> Factorial = Factorial()
>>> Factorial(4)
24
>>>

Getting Pylint E1101 - Instance has no such member

Pylint doesn't like this code:
class sequence(list):
def __init__(self, n):
list.__init__(self)
self += self._generate_collatz_seq(n)
self.pivots = self._generate_pivots()
self.data = self._make_data()
def _collatz_function(self, n):
if n % 2 == 0:
return(int(n/2))
else:
return(3*n + 1)
def _generate_collatz_seq(self, x):
int(x)
sequence_holder = []
while x != 1:
sequence_holder.append(x)
x = self._collatz_function(x)
sequence_holder.append(1)
return sequence_holder
def _generate_pivots(self):
pivots_holder = []
for element in self:
if element % 2 != 0:
pivots_holder.append(element)
return pivots_holder
def _make_data(self):
data_holder = []
data_holder.append(len(self))
data_holder.append(len(self.pivots))
return data_holder
It says
E1101: Instance of 'sequence' has no 'pivots' member(56,36)
This is before I have made any instances of sequence. I'm sure I haven't gone about my task in the most efficient way, but I can't see that I've done anything wrong.

Categories

Resources