Operator knows how to be printed
This commit is contained in:
parent
565a4d3632
commit
3d7018c2c7
@ -3,19 +3,35 @@
|
||||
|
||||
|
||||
from .fraction import Fraction
|
||||
from .generic import flatten_list
|
||||
|
||||
class Operator(str):
|
||||
|
||||
"""The operator class, is a string (representation of the operator) with its arity"""
|
||||
|
||||
PRIORITY = {"^": 5, "/": 4, "*" : 3, ":": 3, "+": 2, "-":2, "(": 1}
|
||||
PRIORITY = {"^": [0, 5], "/": [0, 4], "*" : [0,3], ":": [0,3], "+": [0,1], "-":[2,1]}
|
||||
OPERATIONS = { \
|
||||
"+": ["", "", ("__add__","__radd__")],\
|
||||
"-": ["", "__neg__", ("__sub__", "__rsub__")], \
|
||||
"*": ["", "", ("__mul__", "__rmul__")], \
|
||||
"/": ["", "", ("__div__","__rdiv__")], \
|
||||
"^": ["", "", ("__pow__", "")] \
|
||||
"+": ["", ("__add__","__radd__")],\
|
||||
"-": ["__neg__", ("__sub__", "__rsub__")], \
|
||||
"*": ["", ("__mul__", "__rmul__")], \
|
||||
"/": ["", ("__div__","__rdiv__")], \
|
||||
"^": ["", ("__pow__", "")] \
|
||||
}
|
||||
TXT = { \
|
||||
"+": ["", "{op1} + {op2}"] ,\
|
||||
"-": ["- {op1}", "{op1} - {op2}"] ,\
|
||||
"*": ["", "{op1} * {op2}"] ,\
|
||||
"/": ["", "{op1} / {op2}"] ,\
|
||||
"^": ["", "{op1} ^ {op2}"] ,\
|
||||
}
|
||||
TEX = { \
|
||||
"+": ["", "{op1} + {op2}"] ,\
|
||||
"-": ["- {op1}", "{op1} - {op2}"] ,\
|
||||
"*": ["", "{op1} \\times {op2}"] ,\
|
||||
"/": ["", "\\frac{{ {op1} }}{{ {op2} }}"] ,\
|
||||
"^": ["", "{op1}^{{ {op2} }}"] ,\
|
||||
}
|
||||
|
||||
|
||||
def __new__(cls, operator, arity = 2):
|
||||
op = str.__new__(cls, operator)
|
||||
@ -23,8 +39,10 @@ class Operator(str):
|
||||
|
||||
# TODO: Add op.visibility |sam. nov. 8 17:00:08 CET 2014
|
||||
|
||||
op.priority = cls.PRIORITY[operator]
|
||||
op.actions = cls.OPERATIONS[operator][arity]
|
||||
op.priority = cls.PRIORITY[operator][arity - 1]
|
||||
op.actions = cls.OPERATIONS[operator][arity-1]
|
||||
op._txt = cls.TXT[operator][arity-1]
|
||||
op._tex = cls.TEX[operator][arity-1]
|
||||
|
||||
op.isOperator = 1
|
||||
|
||||
@ -47,6 +65,149 @@ class Operator(str):
|
||||
else:
|
||||
return getattr(args[1], self.actions[1])(args[0])
|
||||
|
||||
def __txt__(self, *args):
|
||||
"""Txt rendering for the operator
|
||||
|
||||
:*args: Operands for this operation
|
||||
:returns: String with operator and his operands
|
||||
|
||||
>>> mul = Operator("*", 2)
|
||||
>>> add = Operator("+", 2)
|
||||
>>> sub1 = Operator("-", 1)
|
||||
>>> div = Operator("/", 1)
|
||||
>>> mul.__txt__(1,2)
|
||||
'1 * 2'
|
||||
>>> add.__txt__(1,2)
|
||||
'1 + 2'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> mul.__txt__(f, 4)
|
||||
'( 2 + 3 ) * 4'
|
||||
>>> f = save_mainOp('-3',sub1)
|
||||
>>> sub1.__txt__(f)
|
||||
'- ( -3 )'
|
||||
>>> sub1.__txt__(-3)
|
||||
'- ( -3 )'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> sub1.__txt__(f)
|
||||
'- ( 2 + 3 )'
|
||||
"""
|
||||
|
||||
#vive le inline? ...
|
||||
replacement = {"op"+str(i+1): ' '.join([str(o) if type(o)==int else o for o in self.add_parenthesis(op)]) for (i,op) in enumerate(args)}
|
||||
|
||||
return self._txt.format(**replacement)
|
||||
|
||||
def __tex__(self, *args):
|
||||
"""Tex rendering for the operator
|
||||
|
||||
:*args: Operands for this operation
|
||||
:returns: String with operator and his operands
|
||||
|
||||
>>> mul = Operator("*", 2)
|
||||
>>> add = Operator("+", 2)
|
||||
>>> sub1 = Operator("-", 1)
|
||||
>>> div = Operator("/", 1)
|
||||
>>> mul.__tex__(1,2)
|
||||
'1 \\\\times 2'
|
||||
>>> add.__tex__(1,2)
|
||||
'1 + 2'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> mul.__tex__(f, 4)
|
||||
'( 2 + 3 ) \\\\times 4'
|
||||
>>> f = save_mainOp('-3',sub1)
|
||||
>>> sub1.__tex__(f)
|
||||
'- ( -3 )'
|
||||
>>> sub1.__tex__(-3)
|
||||
'- ( -3 )'
|
||||
>>> f = save_mainOp('2 + 3',add)
|
||||
>>> sub1.__tex__(f)
|
||||
'- ( 2 + 3 )'
|
||||
"""
|
||||
replacement = {"op"+str(i+1): ' '.join([str(o) if type(o)==int else o for o in self.add_parenthesis(op)]) for (i,op) in enumerate(args)}
|
||||
return self._tex.format(**replacement)
|
||||
|
||||
def __p2i__(self, *args):
|
||||
"""Fix list transformation for the operator
|
||||
|
||||
:*args: Operands for this operation
|
||||
:returns: list with the operator surrounded by operands
|
||||
|
||||
>>> mul = Operator("*", 2)
|
||||
>>> add = Operator("+", 2)
|
||||
>>> sub1 = Operator("-", 1)
|
||||
>>> mul.__p2i__(1,2)
|
||||
[1, '*', 2]
|
||||
>>> f = save_mainOp([2, add, 3],add)
|
||||
>>> mul.__p2i__(f, 4)
|
||||
['(', 2, '+', 3, ')', '*', 4]
|
||||
>>> f = save_mainOp([sub1, 3],sub1)
|
||||
>>> sub1.__p2i__(f)
|
||||
['-', '(', '-', 3, ')']
|
||||
>>> sub1.__p2i__(-3)
|
||||
['-', '(', -3, ')']
|
||||
>>> f = save_mainOp([2, add, 3],add)
|
||||
>>> sub1.__p2i__(f)
|
||||
['-', '(', 2, '+', 3, ')']
|
||||
"""
|
||||
# TODO: Attention à gestion des fractions qui se comportent chelou avec les parenthèses |dim. nov. 9 09:21:52 CET 2014
|
||||
if self.arity == 1:
|
||||
# TODO: Marche juste avec -, il faudra voir quand il y aura d'autres operateurs unitaires |dim. nov. 9 09:24:53 CET 2014
|
||||
op1 = self.add_parenthesis(args[0])
|
||||
return flatten_list([self, op1])
|
||||
|
||||
elif self.arity == 2:
|
||||
op1 = self.add_parenthesis(args[0])
|
||||
op2 = self.add_parenthesis(args[1])
|
||||
return flatten_list([op1, self, op2])
|
||||
|
||||
def add_parenthesis(self, op):
|
||||
""" Add parenthesis if necessary """
|
||||
try:
|
||||
if op.mainOp.priority < self.priority:
|
||||
op = flatten_list(["("] + [op] + [")"])
|
||||
except AttributeError:
|
||||
if type(op) == int and op < 0:
|
||||
op = ['(', op, ')']
|
||||
return flatten_list([op])
|
||||
|
||||
|
||||
|
||||
|
||||
def save_mainOp(obj, mainOp):
|
||||
"""Create a temporary class build over built-in type to stock the main operation of a calculus
|
||||
|
||||
:obj: the object to add the attribute
|
||||
:mainOp: the main operator
|
||||
:returns: the same object with the main operation attribute
|
||||
"""
|
||||
class Fake(type(obj)):
|
||||
""" The fake class """
|
||||
def __new__(cls, obj):
|
||||
op = type(obj).__new__(cls, obj)
|
||||
op.mainOp = mainOp
|
||||
return op
|
||||
|
||||
return Fake(obj)
|
||||
|
||||
if __name__ == '__main__':
|
||||
#op = Operator("+", 2)
|
||||
#print(op.__txt__(1,2))
|
||||
#mul = Operator("*", 2)
|
||||
#add = Operator("+", 2)
|
||||
#sub1 = Operator("-", 1)
|
||||
#div = Operator("/", 1)
|
||||
#print(mul.__txt__(1,2))
|
||||
#print(add.__txt__(1,2))
|
||||
#f = save_mainOp('2 + 3',add)
|
||||
#print(mul.__txt__(f, 4))
|
||||
#f = save_mainOp('-3',sub1)
|
||||
#print(sub1.__txt__(f))
|
||||
#print(sub1.__txt__(-3))
|
||||
#f = save_mainOp('2 + 3',add)
|
||||
#print(sub1.__txt__(f))
|
||||
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user