(Newbie) Restricting inherited methods to operate on element from same subclass
Hi all, Sorry if the post's title is confusing... I'll explain: I have a class, called A say, and N>1 subclasses of A, called A1, A2, A3, ..., AN say. Instances of each subclass can sensibly be joined together with other instances of the *same subclass*. The syntax of the join method is identical for each of the N subclasses, so it would make sense to implement a *single* method called join in the toplevel class A, and then do: a = A1() b = A1() a.join(b) #I want the join method to be inherited from class A d = A2() e = A2() d.join(e) But I want to raise an exception if my code finds: f = A1() g = A2() f.join(g) #should raise exception, as cannot join an #instance of A1 to an instance of A2. How can I verify in a method defined in class A that the subclasses I am joining are exactly the same? Or is there a design flaw here I haven't spotted that makes this a bad idea? Or do I need to code N join methods? Many thanks, Andy -- http://mail.python.org/mailman/listinfo/python-list
Re: (Newbie) Restricting inherited methods to operate on element from same subclass
>Assuming that A is a new-style class then if they have to be >exactly the same type compare the types Ah-ha! I didn't know that. >if the 'other' value can be a subclass of self: > > def join(self, other): > if not isinstance(other, type(self)): > raise whatever Simple and neat! >If A is an old-style class then you would have to compare >the __class__ attribute: self.__class__ != other.__class__ That answered my question perfectly. I'll read up on the new style classes and pick whichever of your solutions fits best. Many thanks, Andy. -- http://mail.python.org/mailman/listinfo/python-list
Re: (Newbie) Restricting inherited methods to operate on element from same subclass
Bruno Desthuilliers wrote: > You've already got the technical answer. About a possible design flaw, > it would seem to me that restricting the join() operation on specific > subclasses breaks the LSP. OTOH, Python being dynamically typed, > inheritence is merely an implementation detail, so that may not be such > a big deal after all... Anyway, you may want to document this point to > make it clear for the next person that'll have to work this code. > > My 2 cents OK, thanks - I see your point. I was in effect implementing mutable objects, similar in some sense to lists, by extending an immutable class similar to Python's tuples. I think instead I should copy the Python type hierarchy, with the list-like and tuple-like classes each defined as sub-classes of a 'sequence' class. In this case the type checking could go away. I'm learning object-orientated programming and dynamic typed languages the hard way at the moment, by trial and error. Can you, or anyone suggest a good book which will guide me? Is there a classic text on this? The coverage of OOP in 'Learning Python' is useful, but I could do with something more in-depth. Thanks again, Andy. -- http://mail.python.org/mailman/listinfo/python-list
Re: problem with the 'math' module in 2.5?
Chris wrote: > sin(pi*0.5) is what I expected, but I expected to get 0 for sin(pi). Computers in general, and Python too, usually use floating point arithmetic in which all numbers are approximated by rational numbers of a particular form (see http://en.wikipedia.org/wiki/Floating_point for details). 1) pi is an irrational number, so it *cannot* be represented exactly in floating point. Therefore the value of pi in your call to the sin function is definitely, proveably, *not* exactly equal to the true value of pi. 2) So, even if the function "sin" could be evaluated exactly, the fact that you are not evaluating it exactly at the true value of pi, but instead at a good but imperfect approximation to this value, means that the sine function *should not* give the result = 0 for your request! 3) The function sin is also evaluated to only a finite degree of precision - just like everything else in floating point arithmetic. Therefore you should not expect absolutely precise results. Instead, you need to understand the limitations of floating point arithmetic, understand the precision you *can* expect, and work within these bounds. It's a good system, but you do need to understand its limitations. The links other people have posted are good resources for this. Best wishes, andy -- http://mail.python.org/mailman/listinfo/python-list
OO design question / Transform object in place?
Hello comp.lang.py, Can you help me with ideas for the following (somewhat newbie) OO design question in Python? Note, I'm using psuedo-code, not actual Python for the examples! Background: --- I need to represent a small variety of mathematical constructs symbolically using Python classes. 1) I have classes, representing numbers, symbolic variables etc. 2) I have classes for groups of these objects, such as a symbolic Sums. 3) To simplify the mathematical constructs, I've provided each of the classes with a simplify(self) method. The following psuedo-code gives an example a = Variable('a') b = Variable('b') two = Number(2) #Yes there are good reason not #to just use Python's int object! :-) expression1 = Sum([a,b,a,a,two]) #This represents a+b+a+a+2 then calling "expression1.simplify()" would invoke Sum.simplify() and reduce expression1 to 3*a+b+2 Question: - Now suppose I set "expression2 = Sum([a,-a])" and Sum.simplify() recognises that the two terms cancel and the Sum has value 0. Can I make "expression2.simplify()" transform expression2 from an instance of Sum to an instance of Number(0) **in place**? Is that possibe, or do I really have to write expression2 = SimplifyFunction(expression2) and use the function return to set expression2 to be a Number(0) object, which is annoying for a variety of reasons! Have I made a mistake in the design? Many thanks, andy. -- http://mail.python.org/mailman/listinfo/python-list
Re: OO design question / Transform object in place?
Dave Benjamin wrote: > [EMAIL PROTECTED] wrote: > > Now suppose I set "expression2 = Sum([a,-a])" and Sum.simplify() > > recognises that the two terms cancel and the Sum has value 0. > > > > Can I make "expression2.simplify()" transform expression2 from an > > instance of Sum to an instance of Number(0) **in place**? Is that > > possibe, or do I really have to write > > I think it's much better for simplify() to return a new object always, > and leave the original object unmodified. You can still write: > > expression2 = expression2.simplify() Dave, A belated thank-you message for your reply to my posting. I took your advice, and made all the simplify methods return new objects and this has simplified my code structure a great deal (and any slow down in run time just doesn't matter!). Am I right that to make "expression2.simplify()" return a new object I will need use copy.copy a lot, as in: def simplify(self): newreturnvalue=copy.copy(self) # #now the code does lots of complicated things #to newreturnvalue object... # return newreturnvalue I have a nagging doubt as to whether this is what you meant, or if I've missed a trick again. Anyway, thanks again for your reply. Yours, Andy. > > if you don't care about the old value. > > > expression2 = SimplifyFunction(expression2) > > This is another valid solution, but it's not an OO solution (you will > need to use "isinstance" to write "SimplifyFunction"). > > > and use the function return to set expression2 to be a Number(0) > > object, which is annoying for a variety of reasons! Have I made a > > mistake in the design? > > It's usually considered poor OO style to have an object change its class > at runtime, although I'm sure you could do it in Python ("__bases__" > would be a place to start) if you really wanted. For what you're trying > to do, I don't think it's necessary, though. > > Dave -- http://mail.python.org/mailman/listinfo/python-list