I want to extend the functionality of a standard list, subclassing seems like the obvious way. Actually, I'm using this to store a mathematical expression in Reverse Polish Notation (RPN) for a genetic programming project.
class RPN(list):
def evaluate(self, vars):
# evaluate the RPN expression
pass
def to_infix(self):
# convert to infix form
pass
@staticmethod
def from_infix(expr):
# create new RPN object from infix expression sting
pass
This works fine, I can create an RPN object like RPN([5, 6, operator.add, 7, 8, operator.add, operator.mult])
, and it works as intended.
My problem is that I want do list-like operations to these RPN objects, such as append, add together, slice, etc. but when I do this they revert back to plain old lists (apart from append - that's ok).
So, for example:
rpn1 = RPN([5, 6, operator.add])
rpn2 = RPN([7, 8, operator.add])
rpn3 = rpn1 + rpn2
# type(rpn3) == list
rpn4 = rpn1[0:1]
# type(rpn4) == list
I can understand why, because a new object gets created, and it creates it as a list. I suppose I can change this behaviour, but then I would have to provide new implementations for __add__
, slicing methods, etc. And all of a sudden, I'm writing a lot more code than I intended. Alternatively, I can remake everything as an RPN object each time, e.g. rpn3 = RPN(rpn1 + rpn2)
, but this also seems clunky.
Is there a better way?
Note, this question was marked as a duplicate of How to use list comprehension in list derived class. The tagged post was asking about how to use list comprehensions inside a derived list class (and in an odd way, by reassigning self variable inside __init__
function), I'm asking about something completely different. It just so happens, that both these are solved by using collections.UserList, but the questions themselves are not duplicates IMHO.
I'm posting this, but @jasonharper provided the answer. The solution to my problem was to subclass collections.UserList
rather than list
. All of its methods generate objects of the same class. Works perfectly.