My program implements a generic coerce_apply function that, given the name of an action and the two arguments as objects of types, units of measurement calculates and returns the result of the action on the arguments, by converting one of the objects to the type of the other object
Copy all the code to see the error that is in the key and I can not solve
class Centimeters(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return 'Centimeters({0})'.format(self.val)
class Inches(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return 'Inches({0})'.format(self.val)
class Feets(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return 'Feets({0})'.format(self.val)
def Inches_to_Centimeters(C):
return Centimeters(C.Inches*2.54)
def add_Centimeters(s,o):
return Centimeters('%.20f' % (s.val + o.val))
def add_Inches(s,o):
return Inches('%.20f' % (s.val + o.val))
def add_Inches_Centimeters(i,c):
return add_Inches(i,centimeter_to_inche(c))
def add_Centimeters_Inches(c, i):
return add_Centimeters(c, inche_to_centimeter(i))
def type_tag(x):
return type_tag.tags[type(x)]
type_tag.tags = {Centimeters: 'cen', Inches: 'inc', Feets: 'fee'}
centimeter_to_inche = lambda x: Centimeters(x.val * 1/2.54)
inche_to_centimeter = lambda x: Inches(x.val * 2.54)
coercions = {('inc', 'cen'): inche_to_centimeter}
def coerce_apply(operator_name, x, y):
tx, ty = type_tag(x), type_tag(y)
if tx != ty:
if (tx, ty) in coercions:
tx, x = ty, coercions[(tx, ty)](x)
elif (ty, tx) in coercions:
ty, y = tx, coercions[(ty, tx)](y)
else:
return 'No coercion possible.'
assert tx == ty
key = (operator_name, tx)
return coerce_apply.implementations[key](x, y)
coerce_apply.implementations = {}
coerce_apply.implementations[('add', ('inc', 'cen'))] = add_Inches_Centimeters
print(coerce_apply('add',Inches(1),Centimeters(150)))
Your approach is convoluted - normally you use classes to combine data with methods to allow f.e. the Centimeter class to handle its own conversion and addition to other units.
You get
File "t.py", line 46, in <module>
print(coerce_apply('add',Inches(1),Centimeters(150)))
File "t.py", line 43, in coerce_apply
return coerce_apply.implementations[key](x, y)
KeyError: ('add', 'cen')
because you are missing the conversion to add centimeters to centimerters in your code.
You can fix it like so (I removed Feets):
class Centimeters(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return 'Centimeters({0})'.format(self.val)
# enable self-addition by other centimeters
def __add__(self, other):
if not isinstance(other, Centimeters):
raise Exception("Bad __add__ call")
self.val += other.val
return Centimeters(self.val + other.val)
class Inches(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return 'Inches({0})'.format(self.val)
# enable self-addition by other Inches
def __add__(self, other):
if not isinstance(other, Inches):
raise Exception("Bad __add__ call")
return Inches(self.val + other.val)
def Inches_to_Centimeters(C):
return Centimeters(C.Inches*2.54)
def add_Centimeters(s,o):
return Centimeters('%.20f' % (s.val + o.val))
def add_Inches(s,o):
return Inches('%.20f' % (s.val + o.val))
def add_Inches_Centimeters(i,c):
return add_Inches(i,centimeter_to_inche(c))
def add_Centimeters_Inches(c, i):
return add_Centimeters(c, inche_to_centimeter(i))
def type_tag(x):
return type_tag.tags[type(x)]
type_tag.tags = {Centimeters: 'cen', Inches: 'inc', Feets: 'fee'}
centimeter_to_inche = lambda x: Centimeters(x.val * 1/2.54)
inche_to_centimeter = lambda x: Inches(x.val * 2.54)
coercions = {('inc', 'cen'): inche_to_centimeter}
def coerce_apply(operator_name, x, y):
tx, ty = type_tag(x), type_tag(y)
if tx != ty:
if (tx, ty) in coercions:
tx, x = ty, coercions[(tx, ty)](x)
elif (ty, tx) in coercions:
ty, y = tx, coercions[(ty, tx)](y)
else:
return 'No coercion possible.'
assert tx == ty
key = (operator_name, (tx,ty))
return coerce_apply.implementations[key](x, y)
coerce_apply.implementations = {}
coerce_apply.implementations[('add', ('inc', 'cen'))] = add_Inches_Centimeters
# add self-addition via classes __add__ method to "conversion"
coerce_apply.implementations[('add', ('cen', 'cen'))] = Centimeters.__add__
print(coerce_apply('add',Inches(1),Centimeters(150)))
Output:
Centimeters(152.54)
Here is the code for the program:
I tried to implement a vector class as i learned about operator overloading in python. I was able to make a vector class which can be used much like a list with operations like len(vector) , vector1 + vector2 (addition operator overloading) and subtraction . But i found a problem. Here is the code of the program and i have stated the problem below :
class vector:
"""Initialize Vector"""
def __init__(self,d):
self.coords = [0]*d
def __len__(self):
return len(self.coords)
def __getitem__(self, item): #Getting an item from a vector
return self.coords[item]
def __setitem__(self, key, value):
self.coords[key] = value
def __add__(self, other):
if(len(self)!= len(other)):
print("Don't add these too ! they are not same types :P")
else:
result = vector(len(self))
for i in range(0,len(result)):
result[i] = self[i] + other[i]
return result
def __sub__(self, other):
if(len(self) != len(other)):
print("Dont subtract these two!")
else:
result = vector(len(self))
for i in range(0,len(result)):
result[i] = self[i] - other[i]
return result
def __eq__(self, other):
return self.coords == other.coords
def __ne__(self, other):
return self.coords != other.coords
def __str__(self):
return '<'+ str(self.coords)[1:-1] +'>'
print("Input for vector 1")
x = vector(2)
for i in range(0,len(x)):
x[i] = int(input('Enter a number\n'))
print("Input for vector 2")
y = vector(2)
for i in range(0,len(y)):
y[i] = int(input('Enter a number\n'))
z = x-y
print(str(x))
print(" + ")
print(str(y))
print(" = ")
print(str(z))
It works if i add a vector + list but list + vector gives an error. How can i implement the other .
You want to implement __radd__. Since it should do the same thing as __add__ here, you can just assign __add__ to it:
class vector:
...
def __add__(self, other):
if(len(self)!= len(other)):
print("Don't add these too ! they are not same types :P")
else:
result = vector(len(self))
for i in range(0,len(result)):
result[i] = self[i] + other[i]
return result
__radd__ = __add__
...
I'm trying to get a RPN calculator by reusing the class CalculatorEngine as follows. But when I run it, it shows an Attribute Error: 'RPNCalculator' object has no attribute 'dataStack'. How do I solve this?
(I didn't include the Stack class as there'd be too much code.)
class CalculatorEngine(object):
def __init__(self):
self.dataStack = Stack()
def pushOperand(self, value):
self.dataStack.push(value)
def currentOperand(self):
return self.dataStack.top()
def performBinary(self, fun):
right = self.dataStack.pop()
left = self.dataStack.top()
self.dataStack.push(fun(left, right))
def doAddition(self):
self.performBinary(lambda x, y: x + y)
def doSubtraction(self):
self.performBinary(lambda x, y: x - y)
def doMultiplication(self):
self.performBinary(lambda x, y: x * y)
def doDivision(self):
try:
self.performBinary(lambda x, y: x / y)
except ZeroDivisionError:
print("divide by 0!")
exit(1)
def doTextOp(self, op):
if (op == '+'):
self.doAddition()
elif (op == '-'):
self.doSubtraction()
elif (op == '*'):
self.doMultiplication()
elif (op == '/'): self.doDivision()
class RPNCalculator(CalculatorEngine):
def __init__(self):
super(CalculatorEngine, self).__init__()
def eval(self, line):
op = line.split(" ")
try:
for item in op:
if item in '+-*/':
self.doTextOp(item)
elif item in '%':
self.performBinary(lambda x, y: x % y)
else:
self.pushOperand(int(item))
return self.currentOperand()
except ZeroDivisionError:
print 'divide by 0!'
class X(object):
def __init__(self, name):
self._name = name
def doit(self, bar):
print("Hello")
class Y(X):
def __init__(self):
# super(X, self).__init__()
X.__init__(self, "DDXX")
i = X("Yuze")
j = Y()
Or you can use this snippet to fix it.
I just made a generic number class.
this class is so simple, descriptions are below
from any ordered character list, make number class representing that ordered character list.
create_number_class("01") returns binary number class
create_number_class("0123456789") returns decimal number class
create_number_class("abcdefghij") return decimal number class but representing each digit as a alphabet.
belows is generic number class definition.
I think it is well-made class definition.
are there something needed improvement in that class definition?
thank you all. always.
ex)
ABC_Class = create_number_class("abc")
x = ABC_Class("baa")
y = ABC_Class("bbb")
print(x+y)
#output digits: abc, v: cbb, decimal_v: 22
below is class definition
def create_number_class(alphabet):
class temp(object):
digits = alphabet
def __init__(self, v):
self.v = v
self.decimal_v = self.to_decimal(self)
#staticmethod
def to_decimal(self):
r = 0
for i in range(0, len(self.v)):
r += len(temp.digits)**(len(self.v)-i-1)*(temp.digits.index(self.v[i]))
return r
#classmethod
def from_decimal(cls, decimal_v):
r = []
mod = len(temp.digits)
if decimal_v < mod:
return cls(temp.digits[decimal_v])
while True:
remainder = decimal_v % mod
r.append(remainder)
decimal_v = int((decimal_v - remainder)/ mod)
if decimal_v < mod:
r.append(decimal_v)
break
r = "".join(list(reversed([temp.digits[x] for x in r])))
#r = "".join(list(reversed([str(temp.digits.index(str(x))) for x in r])))
return cls(r)
def __add__(self, other):
return temp.from_decimal(self.decimal_v+other.decimal_v)
def __sub__(self, other):
return temp.from_decimal(self.decimal_v-other.decimal_v)
def __mul__(self, other):
return temp.from_decimal(self.decimal_v*other.decimal_v)
def __floordiv__(self, other):
return temp.from_decimal(self.decimal_v//other.decimal_v)
def __str__(self):
return "digits: {}, v: {}, decimal_v: {}".format(temp.digits, self.v, self.decimal_v)
def convert_to(self, new_class):
return new_class.from_decimal(self.decimal_v)
return temp
below are example
BinClass = create_number_class("01")
DecimalClass = create_number_class("0123456789")
x = BinClass("111")
x = BinClass("1000")
y = BinClass("10")
HexClass = create_number_class('0123456789ABCDEF')
x = HexClass('1')
y = HexClass('AA')
print(x+y)
print(x-y)
print(x*y)
print(x//y)
print(x.convert_to(DecimalClass))
isinstance(x, BinClass)
I have a code error that I need to debug but I'm not sure where I went wrong. When I run my code I got:
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
c3_plus_0i = create_complex(create_ordinary(3), create_ordinary(0))
File "<pyshell#30>", line 2, in create_complex
return get("make","complex")(x,y)
TypeError: 'NoneType' object is not callable
This is the code that I have:
from generic_arith_min import *
def install_complex_package():
def make_com(x,y):
return tag(repcom(x,y))
def repcom(x,y):
return (x,y)
def real(x):
return x[0]
def imag(x):
return x[1]
def tag(x):
return attach_tag("complex",x)
# add,sub,mul,div: (RepCom, RepCom) -> Generic-Com
def add_com(x,y):
return make_com( add(real(x), real(y)),
add(imag(x), imag(y)) )
def sub_com(x,y):
return make_com( sub(real(x), real(y)),
sub(imag(x), imag(y)) )
def mul_com(x,y):
return make_com(sub(mul(real(x), real(y)),
mul(imag(x), imag(y))),
add(mul(real(x), imag(y)),
mul(real(y), imag(x))))
def div_com(x,y):
com_conj = complex_conjugate(y)
x_times_com_conj = content(mul_com(x, com_conj))
y_times_com_conj = content(mul_com(y, com_conj))
return make_com(div(real(x_times_com_conj), real(y_times_com_conj)),
div(imag(x_times_com_conj), real(y_times_com_conj)));
def complex_conjugate(x):
return (real(x),negate(imag(x)))
def negate_com(x): # (RepCom) -> Generic-Com
return make_com(negate(real(x)), negate(imag(x)))
def is_zero_com(x): # (RepCom) -> Py-Bool
if is_zero(real(x)) and is_zero(imag(x)):
return True
else:
return False
def is_eq_com(x,y): # (RepCom, RepCom) -> Py-Bool
if is_equal(real(x),real(y)) and is_equal(imag(x),imag(y)):
return True
else:
return False
put("make","complex", make_com)
put("add",("complex","complex"), add_com)
put("sub",("complex","complex"), sub_com)
put("mul",("complex","complex"), mul_com)
put("div",("complex","complex"), div_com)
put("negate",("complex",), negate_com)
put("is_zero",("complex",), is_zero_com)
put("is_equal",("complex","complex"), is_eq_com)
def repord_to_repcom(x):
return repcom(create_ordinary(x),create_ordinary(0))
def CCmethod_to_OCmethod(method):
return lambda ord, com: method(repord_to_repcom(ord), com)
def CCmethod_to_COmethod(method):
return lambda com, ord: method(com, repord_to_repcom(ord))
put("add",("ordinary","complex"), CCmethod_to_OCmethod(add_com))
put("add",("complex","ordinary"), CCmethod_to_COmethod(add_com))
put("sub",("ordinary","complex"), CCmethod_to_OCmethod(sub_com))
put("sub",("complex","ordinary"), CCmethod_to_COmethod(sub_com))
put("mul",("ordinary","complex"), CCmethod_to_OCmethod(mul_com))
put("mul",("complex","ordinary"), CCmethod_to_COmethod(mul_com))
put("div",("ordinary","complex"), CCmethod_to_OCmethod(div_com))
put("div",("complex","ordinary"), CCmethod_to_COmethod(div_com))
put("is_equal",("ordinary","complex"), CCmethod_to_OCmethod(is_eq_com))
put("is_equal",("complex","ordinary"), CCmethod_to_COmethod(is_eq_com))
def create_complex(x,y):
return get("make","complex")(x,y)
#################
# Do not change #
#################
n3 = create_ordinary(3)
c3_plus_0i = create_complex(create_ordinary(3), create_ordinary(0))
c2_plus_7i = create_complex(create_ordinary(2), create_ordinary(7))
def gradeThis_complex_package():
complexA = is_equal(n3, c3_plus_0i)
complexB = is_equal(sub(add(n3, c2_plus_7i), c2_plus_7i), n3)
if complexA and complexB:
print("Well done! Your install_complex_package is complete!")
else:
print("Please check your solution for install_complex_package.")
gradeThis_complex_package()
Below is the supported file that it is imported from:
_operation_table = {} #variables with prefixed with an _ are by convention, for internal use and should not be touched.
def attach_tag(tag, content):
return (tag, content)
def type_tag(datum):
if type(datum) == tuple and len(datum) == 2:
return datum[0]
raise Exception('Bad tagged datum -- type_tag ', datum)
def content(datum):
if type(datum) == tuple and len(datum) == 2:
return datum[1]
raise Exception('Bad tagged datum -- content ', datum)
def put(op, types, value):
if op not in _operation_table:
_operation_table[op] = {}
_operation_table[op][types] = value
def get(op, types):
if op in _operation_table and types in _operation_table[op]:
return _operation_table[op][types]
else:
return None
def apply_generic(op, *args):
type_tags = tuple(map(type_tag, args))
proc = get(op, type_tags)
if proc:
return proc(*map(content, args))
raise Exception('No method for these types -- apply_generic', (op, type_tags))
##########################
# Generic Number Package #
##########################
#generic operators we want to support
def add(x,y):
return apply_generic("add", x, y)
def sub(x,y):
return apply_generic("sub", x, y)
def mul(x,y):
return apply_generic("mul", x, y)
def div(x,y):
return apply_generic("div", x, y)
def negate(x):
return apply_generic("negate", x)
def is_zero(x):
return apply_generic("is_zero", x)
def is_equal(x, y):
return apply_generic("is_equal", x, y)
#composite generic operators
def square(x):
return mul(x,x)
#Generic ordinary number package
def install_ordinary_package():
def make_ord(x):
return tag(x)
def tag(x):
return attach_tag("ordinary", x)
# add,sub,mul,div: (RepOrd, RepOrd) -> Generic-OrdNum
def add_ord(x,y):
return make_ord(x+y)
def sub_ord(x,y):
return make_ord(x-y)
def mul_ord(x,y):
return make_ord(x*y)
def div_ord(x,y):
return make_ord(x/y)
def negate_ord(x): # (RepOrd) -> Generic-Ord
return make_ord(-x)
def is_zero_ord(x): # (RepOrd) -> Py-Bool
return x == 0
def is_equal_ord(x,y): # (RepOrd, RepOrd) -> Py-Bool
return x == y
put("make","ordinary", make_ord)
put("negate",("ordinary",), negate_ord)
put("is_zero",("ordinary",), is_zero_ord)
put("add",("ordinary","ordinary"), add_ord)
put("sub",("ordinary","ordinary"), sub_ord)
put("mul",("ordinary","ordinary"), mul_ord)
put("div",("ordinary","ordinary"), div_ord)
put("is_equal",("ordinary","ordinary"), is_equal_ord)
install_ordinary_package()
def create_ordinary(x):
return get("make", "ordinary")(x)
Where exactly did the above code cause the rise to this error? If anyone could help I would really appreciate it. Thank you!
Your _operation_table dictionary does not contain an entry with make and complex therefore your get() function returns None which in fact is not callable.
print("complex" in _operation_table["make"])
False
Perhaps you've forgotten to call install_complex_package (in the same way you called install_ordinary_package) which adds the required function to _operation_table. Once called, your code works fine.