I created a Class that does math with Mixed numbers.
It takes two strings (f1 and f2) ex '1+1/4' and '3+1/5' and can add subtract multiply or divide them.
I was wondering if I could shorten the code using __init__
Can I just pass f1 and f2 to __init__ and reduce the repetition?!
at the moment I have to put the following code into each method which takes in f1 and f2
coef1 = int(f1.split('+')[0])
coef2 = int(f2.split('+')[0])
num1 = int(f1.split('+')[1].split('/')[0])
num2 = int(f2.split('+')[1].split('/')[0])
de1 = int(f1.split('+')[1].split('/')[1])
de2 = int(f2.split('+')[1].split('/')[1])
Each method needs each of those variables to do math
You don't show any classes, where you could use __init__.
First you should write a function:
def parse_mixed_number(f):
coef, numden = f.split('+')
num, den = numden.split('/')
return int(coef), int(num), int(den)
coef1, num1, den1 = parse_mixed_number(f1)
coef2, num2, den2 = parse_mixed_number(f2)
If you want to use classes, then, parse_mixed_number should be called in __init__:
from collections import namedtuple
class MixedNumber(namedtuple("MixedNumber", "coef,num,den")):
def __new__(cls, f):
coef, numden = f.split('+')
num, den = numden.split('/')
return tuple.__new__(cls, [int(coef), int(num), int(den)])
Related
I could not find a similar question based on pytest. Stuck with this for quite sometime. Please do not close this until it is answered. thank you.
The python class looks like:
class Calculator:
def __init__(self, num1=None, num2=None):
self.logger = get_logger(__name__)
self.num1 = num1
self.num2 = num2
def calculate(self):
if self.num1 and self.num2:
num = self.__divider(num1, num2)
else:
raise Exception('num2 cannot be 0')
return self.__faulty_displayer(num)
def __divider(self, num1, num2):
value = num1/num2
return value
def __faulty_displayer(self,num)
value = num + 1
return value
What I want to be able to do is, write a pytest for calculate() method. But, I am unable to do so, as I am unable to call the method with any values. So, inherently, every time, the exception is getting called.
What I have tried so far is:
import pytest
#pytest.fixture
def obj():
return Calculator()
# Need help in writing a test case which can take the values of num1, and num2
def test_calculate(obj):
expected_value = 1
actual_value = obj.calculate() #How to pass num1, and num2 values
assert expected_value == actual_value
The way that your class is defined, num1 and num2 have to be defined at the time the object is constructed. This is an awkward design (as you're discovering now in trying to write your test), but assuming that we need to work with that class as-is instead of fixing it, then the test needs to construct the object with the test values, like this:
def test_calculate(num1, num2, expected):
"""Test that Calculator.calculate() produces the expected result."""
assert Calculator(num1, num2).calculate() == expected
test_calculate(1, 1, 2) # 1 / 1 + 1 = 2
test_calculate(4, 2, 3) # 4 / 2 + 1 = 3
This question already has answers here:
TypeError: Missing 1 required positional argument: 'self'
(8 answers)
Closed 6 months ago.
This is my first attempt at creating and using a class. The error is occurring when I ask the user for input. I'm getting the following error:
n1 = Arithmetic.float_input("Enter your First number: ")
TypeError: float_input() missing 1 required positional argument: 'msg'
Here is my code.
# Define class
class Arithmetic:
def float_input(self, msg): # Use this function for exception handling during user input
while True:
try:
return float(input(msg))
except ValueError:
print("You must enter a number!")
else:
break
def add(self, n1, n2):
sum1 = n1 + n2
print(n1,"+" ,n2,"=", sum1)
def sub(self, n1, n2):
diff = n1 - n2
print(n1,"-",n2,"-", diff)
def mult(self, n1, n2):
product = n1 * n2
print(n1,"*",n2, "=", product)
def div(self, n1, n2):
if n2 == 0:
print(n1, "/",n2,"= You cannot divide by Zero")
else:
quotient = n1 / n2
print(n1, "/",n2,"=", quotient)
def allInOne(self, n1, n2):
#Store values in dictionary (not required, just excercising dictionary skill)
res = {"add": add(n1, n2), "sub": sub(n1, n2), "mult": mult(n1, n2), "div": div(n1, n2)}
# Declare variables. Ask user for input and use the exception handling function
n1 = Arithmetic.float_input("Enter your First number: ")
n2 = Arithmetic.float_input("Enter your Second number: ")
What am I missing?
If you're coming from a Java background, it's worth knowing you really usually don't need to wrap methods in classes in Python unless you need state provided by self.
Anyway, the error you're seeing is because your methods aren't marked #classmethod or #staticmethod and thus require an instance of the class and you're just calling them via the class itself (so no implicit instance or class object is passed in as the first parameter).
Thus your options are:
1 – create an instance of Arithmetic() and use it:
arith = Arithmetic()
n1 = arith.float_input("Enter your First number: ")
n2 = arith.float_input("Enter your Second number: ")
2 – mark the methods static, e.g.
#staticmethod
def float_input(prompt): # note: no `self`
3 – mark the methods classmethods, e.g.
#classmethod
def float_input(cls, prompt): # `cls` is `Arithmetic` (or its subclass) itself
4 – make the methods just regular functions without a class.
The problem is that you did not create an instance of Arithmetic before calling the method. Because you did not create an object, no instances will be passed to the self parameter. This causes the message "Enter your first number:" to be passed to the self parameter and the msg parameter to be empty.
To fix the problem, simply create an object using parentheses after the class name, example:
# Declare variables. Ask user for input and use the exception handling function
n1 = Arithmetic().float_input("Enter your First number: ")
n2 = Arithmetic().float_input("Enter your Second number: ")
If you did not create an object on purpose, you can use the #classmethod class decorator to pass the class name to the self parameter.
# Define class
class Arithmetic:
#classmethod
def float_input(class_, msg): # Use this function for exception handling during user input
while True:
try:
return float(input(msg))
except ValueError:
print("You must enter a number!")
else:
break
# Code...
n1 = Arithmetic.float_input("Enter your First number: ")
n2 = Arithmetic.float_input("Enter your Second number: ")
There is also another decorator named #staticmethod. If you use this decorator, you can call the method without having an instance of Arithmetic and without having to define self in the method signature. Example:
class Arithmetic:
#staticmethod
def float_input(msg): # Use this function for exception handling during user input
while True:
try:
return float(input(msg))
except ValueError:
print("You must enter a number!")
else:
break
# Code...
n1 = Arithmetic.float_input("Enter your First number: ")
n2 = Arithmetic.float_input("Enter your Second number: ")
fix as:
# Declare variables. Ask user for input and use the exception handling function
arithmatic = Arithmetic()
n1 = arithmatic.float_input("Enter your First number: ")
n2 = arithmatic.float_input("Enter your Second number: ")
its better to instantiate the class first, and then use the proper method of it, like below
n1 = new Arithmetic()
n1.float_input('Enter your First number: ')
I'm trying to make a chopsticks game. Here's a wikipedia link to the game https://en.wikipedia.org/wiki/Chopsticks_(hand_game). So far I just added a couple methods so that one hand can attack another hand using the 'attack' method. I feel like the code I wrote is very verbose, ugly and maybe even wrong though. How can I write this more elegantly?
class game:
def __init__(self):
self.x_left = 1
self.x_right = 1
self.o_left = 1
self.o_right = 1
def set_x_left(self, num):
self.x_left = num
def set_x_right(self, num):
self.x_right = num
def set_o_left(self, num):
self.o_left = num
def set_o_right(self, num):
self.o_right = num
def dict_func(self, hand):
self.func= {'x_left': self.set_x_left, 'x_right': self.set_x_right,
'o_left': self.set_o_left, 'o_right': self.set_o_right}
return self.func[hand]
def dict_hand(self, hand):
self.hands = {'x_left': self.x_left, 'x_right': self.x_right,
'o_left': self.o_left, 'o_right': self.o_right}
return self.hands[hand]
def attack(self, from_hand, to_hand):
self.dict_func(to_hand)(self.dict_hand(from_hand) + self.dict_hand(to_hand))
your code seems to have some unnecessary methods. You can get rid of the methods that set the variables with a number:
def set_x_left(self, num):
self.x_left = num
When you create an instance of game you can use dot notation to set the values:
chopsticks = game()
# ^^^ that's the instance
chopsticks.set_x_left(0)
# is the same as
chopsticks.x_left = 0
As you can see it's quicker to type, doesn't require any methods. It's just attribute assignments. Doing this will affect you dict_func method, so you can create an anonymous function instead:
def dict_func(self, hand):
self.func = {'x_left': lambda self, x: self.x_left = x,
'x_right': lambda self, x: self.x_right = x,
'o_left': lambda self, x: self.o_left = x,
'o_right': lambda self, x: self.o_right = x}
return self.func[hand]
In fact you can declare the self.func self.hands attributes in __init__ to make sure that they're only assigned to once. Then in the function you can just write return self.func[hand]
Your dict_hand method is also slightly over complicated. Your aim is to get the attribute from the instance dict, so you can do:
def dict_hand(self, hand):
return getatttr(self, hand)
(You may want to rename this function :))
In this example I want to do a menu with commands (add 2 numbers and sub 2 numbers). I would like to do this with a dictionary where I want to assign to the key value the method add and sub. When I call the method UI,the key values are called. How to fix it?
class Calc():
def __init__(self):
pass
def add(self):
a = int(input("Number a is:"))
b = int(input("Number b is:"))
return a + b
def sub(self):
a = int(input("Number a is:"))
b = int(input("Number b is:"))
return a + b
def UI(self):
Options = {1:self.add(), 2:self.sub()}
n = Calc()
n.UI()
I would recommend not adding function calls to dict's as it will likely just add confusion to your code. However if you have to do it that way you can store the pointers to the functions.
Options = {1:self.add,
2:self.sub
}
Which can than be called like
Options1
A quick working example based on your original code:
class Calc():
def __init__(self):
pass
def add(self):
a = int(input("Number a is:"))
b = int(input("Number b is:"))
return a + b
def sub(self):
a = int(input("Number a is:"))
b = int(input("Number b is:"))
return a + b
def UI(self, option):
Options = {1:self.add,
2:self.sub
}
return Options[option]()
n = Calc()
n.UI(1)
Number a is:1
Number b is:1
2
The code:
Options = {1:self.add(),
2:self.sub()
}
actually calls the add and sub methods once when the dictionary is created. You want the methods to be called when the user selects an option from the menu. You could do it with this as your UI() method instead:
def UI(self):
options = {1:self.add,
2:self.sub}
while True:
# get user selection
selection = input("1. add\n2: subtract\nSelection: ")
if selection.lower().startswith('q'):
# any input starting with "Q" or "q" quits
break
# call method corresponding to the user's selection
result = options[int(selection)]()
# error handling omitted
print("Result: {}".format(result))
P.S. your sub() method actually adds.
Update
You now require that the parameters for the various operations be passed to the method. This means that the parameters must be collected externally to the method. Here is one such way:
import operator
class Calc:
def my_div(self, a, b):
return a / float(b) # ensure float division
def UI(self):
options = {1: operator.add,
2: operator.sub,
3: self.my_div,}
while True:
# get user selection
selection = input("1. add\n2: subtract\n3: divide\nq: quit\nSelection: ")
if selection.lower().startswith('q'):
# any input starting with "Q" or "q" quits
break
selection = int(selection)
if selection not in options:
print("Invalid selection, try again")
continue
# get arguments to pass to operation
a = int(input("Number a is:"))
b = int(input("Number b is:"))
# call method corresponding to the user's selection
result = options[selection](a, b)
# error handling omitted
print("Result: {}".format(result))
It's optional, but you no longer need to define your own add(), sub(), etc. methods. You can simply use those provided by the operator module as shown above, or you can implement your own also as shown above.
This assumes that all operations require the same number of arguments. If that is not the case then you could set your dictionary to contain tuples with the function and required number of arguments:
options = {1: (operator.add, 2),
2: (operator.sub, 2),
3: (self.my_div, 2),
4: (operator.neg, 1), # N.B. unary operator
}
Then, when you get the arguments from the user:
# get arguments to pass to operation
function, n_args = options[selection]
args = [int(input("Number {} is:".format(i+1))) for i in range(n_args)]
Finally, call the method:
result = function(*args)
which will unpack the arguments and pass them into the corresponding function.
First you need to change your dictionary to something like this:
options = {1:self.add, 2:self.sub}
so python does not call the methods when the dict is crated, but stores the method reference in options as values.
Now you can call (ie. execute) a method in options by calling
options[some_key]()
or (as you wanted)
options[1]() #add
options[2]() #sub
I've been implementing a model with spark via a python class. I had some headaches calling class methods on a RDD defined in the class (see this question for details), but finally have made some progress. Here is an example of a class method I'm working with:
#staticmethod
def alpha_sampler(model):
# all the variables in this block are numpy arrays or floats
var_alpha = model.params.var_alpha
var_rating = model.params.var_rating
b = model.params.b
beta = model.params.beta
S = model.params.S
Z = model.params.Z
x_user_g0_inner_over_var = model.x_user_g0_inner_over_var
def _alpha_sampler(row):
feature_arr = row[2]
var_alpha_given_rest = 1/((1/var_alpha) + feature_arr.shape[0]*(1/var_rating))
i = row[0]
items = row[1]
O = row[3] - np.inner(feature_arr,b) - beta[items] - np.inner(S[i],Z[items])
E_alpha_given_rest = var_alpha_given_rest * (x_user_g0_inner_over_var[i] + O.sum()/var_rating)
return np.random.normal(E_alpha_given_rest,np.sqrt(var_alpha_given_rest))
return _alpha_sampler
As you can see, to avoid serialization errors, I define a static method that returns a function that is in turn applied to each row of an RDD (model is the parent class here, and this is called from within another method of model):
# self.grp_user is the RDD
self.params.alpha = np.array(self.grp_user.map(model.alpha_sampler(self)).collect())
Now, this all works fine, but is not leveraging Spark's broadcast variables at all. Ideally, all the variables I'm passing in this function (var_alpha, beta, S, etc.) could first be broadcast to the workers, so that I wasn't redundantly passing them as part of the map. But I'm not sure how to do this.
My question, then, is the following: How/where should I make these into broadcast variables such that they are available to the alpha_sampler function that I map to grp_user? One thing I believe will work would be to make them globals, e.g.
global var_alpha
var_alpha = sc.broadcast(model.params.var_alpha)
# and similarly for the other variables...
Then the alpha_sampler could be much simplified:
#staticmethod
def _alpha_sampler(row):
feature_arr = row[2]
var_alpha_given_rest = 1/((1/var_alpha.value) + feature_arr.shape[0]*(1/var_rating.value))
i = row[0]
items = row[1]
O = row[3] - np.inner(feature_arr,b.value) - beta.value[items] - np.inner(S.value[i],Z.value[items])
E_alpha_given_rest = var_alpha_given_rest * (x_user_g0_inner_over_var.value[i] + O.sum()/var_rating.value)
return np.random.normal(E_alpha_given_rest,np.sqrt(var_alpha_given_rest))
But of course this is really dangerous use of globals that I would like to avoid. Is there a better way that lets me leverage broadcast variables?
Assuming that variables you use here are simply scalars there is probably nothing to gain here from a performance perspective and using broadcast variables will make you code less readable but you can either pass a broadcast variable as an argument to the static method:
class model(object):
#staticmethod
def foobar(a_model, mu):
y = a_model.y
def _foobar(x):
return x - mu.value + y
return _foobar
def __init__(self, sc):
self.sc = sc
self.y = -1
self.rdd = self.sc.parallelize([1, 2, 3])
def get_mean(self):
return self.rdd.mean()
def run_foobar(self):
mu = self.sc.broadcast(self.get_mean())
self.data = self.rdd.map(model.foobar(self, mu))
or initialize it there:
class model(object):
#staticmethod
def foobar(a_model):
mu = a_model.sc.broadcast(a_model.get_mean())
y = a_model.y
def _foobar(x):
return x - mu.value + y
return _foobar
def __init__(self, sc):
self.sc = sc
self.y = -1
self.rdd = self.sc.parallelize([1, 2, 3])
def get_mean(self):
return self.rdd.mean()
def run_foobar(self):
self.data = self.rdd.map(model.foobar(self))