How to pass method name as an argument while calling another method? - python-3.x

I am writing a class wherein I want to use a metric to calculate the score. I should be able to pass the metric as an argument based on which I want to calculate a score. Here is the code I have written. Is there a better approach to solving this situation?
class A:
def __init__(self, region):
self.region = region
def metric1(self, a, b):
returns a*b
def metric2(self, a, b, c):
return self.metric1(a, b) + c
def evaluate(self, metric, a, b, c = None):
if metric = 'metric1':
score = self.metric1(a,b)
elif metric = 'metric2':
score = self.metric2(a,b,c)
return score[0]
obj1 = A('XYZ')
obj1.evaluate('metric2', a, b, c)
Furthermore, I want to write another method that would use the output of the evaluate method to do some other calculations. Is this the right approach to writing a class when we have this chain of outputs from previous methods used in subsequent methods? Or, can we leverage decorators here somehow?

You can access method inside a class by className.methodName (A.metric1) or object.methodName (obj1.metric1)
class A:
def __init__(self, region):
self.region = region
def metric1(self, a, b):
return a*b
def metric2(self, a, b, c):
return self.metric1(a, b) + c
def evaluate(self, metric, a, b, c = None):
if metric == A.metric1:
score = self.metric1(a,b)
elif metric == A.metric2:
score = self.metric2(a,b,c)
return score
obj1 = A('XYZ')
print(obj1.evaluate(A.metric1, a=1, b=2)) # 2
print(obj1.evaluate(A.metric2, a=1, b=2, c=3)) # 5
My approach of writing such class.
class A:
def __init__(self, region, a, b, c=None):
self.region = region
self.a = a
self.b = b
self.c = c
def metric1(self):
return self.a * self.b
def metric2(self):
return A.metric1(self) + self.c
obj1 = A('XYZ', 1, 2, 3)
print(A.metric1(obj1)) # 2
print(A.metric2(obj1)) # 5

Related

Decorator to get even numbers from Fibonacci

I got a task on courses: Create Fibonacci generator function and create a decorator to leave only even numbers in this sequence. I tried but had no success. Lower I add a code which I try to create.
def decorator(func):
def inner(*args, **kwargs):
print("start decorator")
value = func(*args, **kwargs)
if a%2==0:
print(a)
return value
print("finish decorator")
return inner
#decorator
def fib(n):
a, b = 0, 1
for __ in range(n):
# if a%2==0:
yield a
a, b = b, a + b
print(list(fib(10)))
Please, help to find a way to solve it.

Multilevel and Multiple inheritance using super() in Python returns odd result

if I type this this code,
class A:
pass
class B(A):
def show_letter(self):
print("This is B")
class C(B):
def show_letter(self):
super().show_letter()
print("This is C")
class E(B):
def show_letter(self):
super().show_letter()
print("This is E")
class D(C, E):
division = "North"
def show_letter(self):
super().show_letter()
print("This is D")
div1 = D()
div1.show_letter()
it returns:
This is B
This is E
This is C
This is D
Why is there "E" printed ?
If I delete super() in C class, "E" is not printed.
Thank you.
This is because the method resolution order. The first call is in D, then it calls C due to the arguments order: D(C, E). It could call B as parent but the latter is also a parent for E, so it is called the first. Only after that there is a B call. Thereby your call order is D -> C -> E -> B & the print order is revered.

Modifying an instance of a class when it is created

I have this code:
class Fraction:
def __init__(self, top, bottom):
self.num = top
self.den = bottom
self = self.to_lowest_form()
def to_lowest_form(self):
from math import gcd
d = 0
while d != 1:
d = gcd(self.num, self.den)
self.num //= d
self.den //= d
return Fraction(self.num, self.den)
def __add__(self, other):
pass
As above code shows, I need to get a fraction then put it to its lowest form after it is initialized.
(I get a RecursionError and I know why).
So my question is how can i convert a newly created fraction to its lowest term (so as to avoid calling instance.lowest_form() in every method) ?
You're just making things more complicated by returning a new instance of Fraction when reducing the numerator/denominator in the to_lowest_form method, instead of returning the reduced numbers themselves. Consider keeping the reduced numbers as attributes instead, after calculating their reduced form internally.
Implementation example:
from math import gcd
class Fraction:
def __init__(self, top, bottom):
self.num, self.den = self.reduce(num=top, den=bottom)
#staticmethod
def reduce(num, den):
d = 0
while d != 1:
d = gcd(num, den)
num //= d
den //= d
return num, den

Pass list values into class with a loop in Python

I am trying to pass multiple input entries i as arguments into class Student(). After the last iteration (m), I get a type error. I already tried a for-loop as well, but it didn't work either. Thanks for your help!
class Student():
def __init__(self, d, a, b, c):
self.d = d
self.a = a #name
self.b = b #roll
self.c = c #percentage
return#
def uid(self):
print('UID:', self.d)
def name(self):
print('Name:', self.a)
def roll(self):
print('Roll:', self.b)
def perc(self):
print('Perc:', self.c)
#THIS IS WHAT YOUR INPUT SHOULD LOOK LIKE:
#Peter 405 100
m = input('how many entries? ')
n = 0
while n < int(m):
i = input()
j = i.split()
o = Student(n,*j)
o.uid(), o.name(), o.roll(), o.perc()
n+=1
Student()
The last line - Student() creates an instance of the class without providing any arguments. Hence, Python raises a type error.
Deleting this line (or entering the arguments) will fix the problem.

how to get the updated size of dynamic array in python

How should I edit my code?
import ctypes
import sys
class DynamicArray(object):
def __init__(self):
self.n = 0 #counter
self.capacity = 1
self.A = self.make_array(self.capacity)
def __len__(self):
'''Returns the number of elements'''
b = sys.getsizeof(self.A)
print(b)
return self.n
def __getitem__(self,k):
'''Return elements in array with specified Index'''
if not 0<=k<self.n:
return IndexError('Index out of bounds')
return self.A[k]
def append(self,ele):
'''Add element in the array'''
if self.n==self.capacity:
self._resize(2*self.capacity)
self.A[self.n]=ele
self.n+=1
def _resize(self,new_cap):
B = self.make_array(new_cap)
for k in range(self.n):
B[k]=self.A[k]
self.A = B
self.capacity = new_cap
def make_array(self,new_cap):
'''Make a raw array using ctype module'''
return (new_cap*ctypes.py_object)()
arr = DynamicArray()
arr.append(1)
len(arr)
Output:
80
1
arr.append(1)
len(arr)
Output:
80
2
see https://docs.python.org/3/library/sys.html#sys.getsizeof
from doc:
Return the size of an object in bytes. The object can be any type of
object. All built-in objects will return correct results, but this
does not have to hold true for third-party extensions as it is
implementation specific.
Only the memory consumption directly attributed to the object is
accounted for, not the memory consumption of objects it refers to.
I hope it is clear.

Resources