Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #83274
| Date | 2015-01-06 18:01 -0800 |
|---|---|
| From | Andrew Robinson <andrew3@r3dsolutions.com> |
| Subject | Re: Comparisons and sorting of a numeric class.... |
| References | <54ABB88A.7070504@r3dsolutions.com> <54ABC52A.1050507@davea.name> <54ABE383.3020801@r3dsolutions.com> <54ABEAD9.8070000@davea.name> |
| Newsgroups | comp.lang.python |
| Message-ID | <mailman.17424.1420596200.18130.python-list@python.org> (permalink) |
On 01/06/2015 06:02 AM, Dave Angel wrote: > On 01/06/2015 08:30 AM, Andrew Robinson wrote: >> >>>> So, I'm not sure I can subclass boolean either because that too is a >>>> built in class ... but I'm not sure how else to make an object that >>>> acts as boolean False, but can be differentiated from false by the >>>> 'is' >>>> operator. It's frustrating -- what good is subclassing, if one cant >>>> subclass all the base classes the language has? > > I said earlier that I don't think it's possible to do what you're > doing without your users code being somewhat aware of your changes. Aye. You did. And I didn't disagree. :) The goal is merely to trip up those who don't know what I'm doing as little as possible and only break their code where the very notion of uncertainty is incompatible with what they are doing, or where they did something very stupid anyway... eg: to break it where there is a good reason for it to be broken. I may not achieve my goal, but I at least hope to come close... > > But as long as the user doesn't check for the subclass-ness of your > bool-like function, you should manage. In Python, duck-typing is > encouraged, unlike java or C++, where the only substitutable classes > are subclasses. but if you can't subclass a built in type -- you can't duck type it -- for I seem to recall that Python forbids duck typing any built in class nut not subclasses. So your two solutions are mutually damaged by Guido's decision; And there seem to be a lot of classes that python simply won't allow anyone to subclass. ( I still need to retry subclassing float, that might still be possible. ) Removing both options in one blow is like hamstringing the object oriented re-useability principle completely. You must always re-invent the wheel from near scratch in Python.... >> >> --Guido van Rossum >> >> So, I think Guido may have done something so that there are only two >> instances of bool, ever. >> eg: False and True, which aren't truly singletons -- but follow the >> singleton restrictive idea of making a single instance of an object do >> the work for everyone; eg: of False being the only instance of bool >> returning False, and True being the only instance of bool returning >> True. >> >> Why this is so important to Guido, I don't know ... but it's making it >> VERY difficult to add named aliases of False which will still be >> detected as False and type-checkable as a bool. If my objects don't >> type check right -- they will likely break some people's legacy code... >> and I really don't even care to create a new instance of the bool object >> in memory which is what Guido seems worried about, rather I'm really >> only after the ability to detect the subclass wrapper name as distinct >> from bool False or bool True with the 'is' operator. If there were a > > There's already a contradiction in what you want. You say you don't > want to create a new bool object (distinct from True and False), but > you have to create an instance of your class. If it WERE a subclass > of bool, it'd be a bool, and break singleton. Yes there seems to be a contradiction but I'm not sure there is ... and it stems in part from too little sleep and familiarity with other languages... Guido mentioned subclassing in 'C' as part of his justification for not allowing subclassing bool in python. That's what caused me to digress a bit... consider: In 'C++' I can define a subclass without ever instantiating it; and I can define static member functions of the subclass that operate even when there exists not a single instance of the class; and I can typecast an instance of the base class as being an instance of the subclass. So -- (against what Guido seems to have considered) I can define a function anywhere which returns my new subclass object as it's return value without ever instantiating the subclass -- because my new function can simply return a typecasting of a base class instance; The user of my function would never need to know that the subclass itself was never instantiated... for they would only be allowed to call static member functions on the subclass anyway, but all the usual methods found in the superclass(es) would still be available to them. All the benefits of subclassing still exist, without ever needing to violate the singleton character of the base class instance. So part of Guido's apparent reason for enforcing singleton ( dual singleton / dualton? ) nature of 'False' and 'True' isn't really justified by what 'C++' would allow because C++ could still be made to enforce singleton instances while allowing subclassing *both* at the same time. There seems to be some philosophical reason for what Guido wants that he hasn't fully articulated...? If I understood him better-- I wouldn't be making wild ass guesses and testing everything I can think of to work around what he chose... > > > If you ignore your subclass "requirement," 'is' should do the right > thing. Whatever your class instance is, it won't be the same object > as True or as False. It was never a requirement; It was an experiment to see how close I could get to identical behavior. It didn't work... it will have to be discarded... Therefore, I know I will break some peoples code... > >> way to get the typecheck to match, > > That's a piece of legacy code which you won't be able to support, as > far as I can see. > Yep. Python cuts off re-usability at the ankles... I have NO way to signal to my users that my object is compatible with bool. For that's what subclass typechecks are about... If someone *needs* an object that does everything bool does (proto-type bool), the only portable test for compatibility is to check if the object is a bool... That pretty much kills legacy support / compatability... no one can know my object is compatible with bool in a portable fashion... >> I wouldn't mind making a totally >> separate class which returned the False instance; eg: something like an >> example I modified from searching on the web: >> >> class UBool(): >> def __nonzero__(self): return self.default >> def __init__( self, default=False ): self.default = bool(default) >> def default( self, default=False ): self.defualt = bool(default) >> >> but, saying: >> >>> error=UBool(False) >> >>> if error is False: print "type and value match" >> ... >> >>> >> >> Failed to have type and value match, and suggests that 'is' tests the >> type before expanding the value. > > Not at all. It doesn't check the type or the value. It checks > whether it's the SAME object. > DOOOOOOH!!!! I hate ever having learned PHP before I learned python. I bet you can guess what version of 'is' I remembered the rule for when overtired... >> It's rather non intuitive, and will break code -- for clearly error >> expands to 'False' when evaluated without comparison functions like ==. >> >> >>> if not error: print "yes it is false" >> ... >> yes it is false > > No, the object False is not referenced in the above expression. You're > checking the "falseness" of the expression. Same as if you say > if not 0 > if not mylist Hmm... your a bit confusing / unclear ? I think the object returned by 'not' is True or False. So the expression as a whole does reference either False or True objects. I didn't think that 'error' was the False object itself, just that the evaluation of any expression containing 'error' eventually called __nonzero__() which I defined to return the False object. What I was trying to figure out is order of precedence ; when does __nonzero__() get called, and is it called at all. I think it was called, because the object reference itself is something that is a non null pointer... and I would expect 'not (...something nonzero.,.) ' to evaluate as false and the print statement NOT to be executed. However, the print statement was executed -- so that possibility was eliminated. So, I am pretty sure that at some point __nonzero__() was called, and error was replaced with whatever __nonzero__() returned; In my test, that would be the 'False' object. Correct? > >> >>> print error.__nonzero__() >> False >> >>> if error==False: print "It compares to False properly" >> ... > > You control this one by your __eq__ method. Yes... now we're really getting somewhere. That's something I overlooked. Question: If two different class's instances are being compared by '==', and both define an __eq__ method, which method gets called? ( I don't know if that applied here... but I'm not familiar with order of operations ) > 1) read up more closely on special methods, and on the meanings of > id() and 'is' > > 2) And don't expect that any change you make at this level could be > transparent to all existing applications. It's a contradiction in terms. > > 1) Yes -- I'll do that. although -- my interpretation of 'is' was simply tiredness... I knew better and forgot. You put my head back on right. Thanks. 2) I never did have that expectation ; I just want to do the best I can... and not settle for third best... Thanks. :) To sum up: It's fairly clear that whenever my library returns actual True and False objects from magnitude comparison operators, there will be full backward compatibility with float. So -- for cases where the two numeric types don't have any difference in meaning, there will still be full compatibility. (That, thankfully, is the most typical use case...) For the remaining quasi 'False' return values, I know the 'is' operator must always fail. So if anyone stupidly puts '(a>b) is False' in their legacy floating point code for no really good reason -- well, too bad; it breaks -- But that's the best I can do. However; I think I can still hope to be compatible with '(a>b) == False' by defining my own '==' operator ; and still allow users an explicit 'is' test for my singleton-like instances of PartTrue, Unknown, and PartFalse so that they can distinguish them from an actual 'False' object... I think I can also define a relative certainty magnitude operator for falseness so users can test if PartTrue is more true than False. ( PartTrue > False ) etc. and thereby allow them to make their own custom sorts based on relative true-ness when needed. And, finally, on the sort operation consistency you mentioned in an earlier email -- your comments, and another posters, about that is well taken. It's something I'll have to review again later... but in essence, I don't think it's a problem because whenever two variables are definitely '>' or '<' each other with an actual True or False object returned -- I already know the consistency with respect to a third variable will hold. On the other hand, By definition, all quasi false values return false for both '>' and '<', so what ends up happening is that python treats any uncertainty as if the variables were equal, and so they are grouped together but left in the same order as they were originally sent to the search. (stable). But I don't think that stops me from treating the sort order of all items which are quasi-equal, as a second search (hierarchical search). eg: Sort first by definite magnitude, then among those deemed 'equal', sort them by average expectation value... That's going to be good enough for me and my users, for the sort order of truly quasi equal things is arbitrary anyway... as long as it's not 'defintely wrong' they'll have no reason to complain.
Back to comp.lang.python | Previous | Next — Next in thread | Find similar | Unroll thread
Re: Comparisons and sorting of a numeric class.... Andrew Robinson <andrew3@r3dsolutions.com> - 2015-01-06 18:01 -0800
Re: Comparisons and sorting of a numeric class.... Steven D'Aprano <steve@pearwood.info> - 2015-01-07 08:10 +0000
Re: Comparisons and sorting of a numeric class.... Chris Angelico <rosuav@gmail.com> - 2015-01-07 19:21 +1100
Re: Comparisons and sorting of a numeric class.... Marko Rauhamaa <marko@pacujo.net> - 2015-01-07 12:01 +0200
Re: Comparisons and sorting of a numeric class.... Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-08 10:46 +1100
Re: Comparisons and sorting of a numeric class.... Marko Rauhamaa <marko@pacujo.net> - 2015-01-08 08:21 +0200
Re: Comparisons and sorting of a numeric class.... Ian Kelly <ian.g.kelly@gmail.com> - 2015-01-08 07:57 -0700
Re: Comparisons and sorting of a numeric class.... Marko Rauhamaa <marko@pacujo.net> - 2015-01-08 21:41 +0200
Re: Comparisons and sorting of a numeric class.... Chris Kaynor <ckaynor@zindagigames.com> - 2015-01-08 10:44 -0800
Re: Comparisons and sorting of a numeric class.... Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-09 23:27 +1100
Re: Comparisons and sorting of a numeric class.... Chris Angelico <rosuav@gmail.com> - 2015-01-09 23:43 +1100
Re: Comparisons and sorting of a numeric class.... Marko Rauhamaa <marko@pacujo.net> - 2015-01-09 16:28 +0200
Re: Comparisons and sorting of a numeric class.... Paul Rubin <no.email@nospam.invalid> - 2015-01-09 07:06 -0800
Re: Comparisons and sorting of a numeric class.... Chris Angelico <rosuav@gmail.com> - 2015-01-10 02:14 +1100
Re: Comparisons and sorting of a numeric class.... Marko Rauhamaa <marko@pacujo.net> - 2015-01-09 17:16 +0200
csiph-web