Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #83641
| Path | csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!news.albasani.net!news.stack.nl!newsfeed.xs4all.nl!newsfeed4.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail |
|---|---|
| Return-Path | <andrew3@r3dsolutions.com> |
| X-Original-To | python-list@python.org |
| Delivered-To | python-list@mail.python.org |
| X-Spam-Status | OK 0.000 |
| X-Spam-Evidence | '*H*': 1.00; '*S*': 0.00; 'broken': 0.04; 'guido': 0.05; 'url:pipermail': 0.05; '"""': 0.07; 'modified': 0.07; 'practice,': 0.07; 'reason,': 0.07; 'revision': 0.07; 'source.': 0.07; 'alternatives': 0.09; 'assumed': 0.09; 'differently.': 0.09; 'except:': 0.09; 'explanation': 0.09; 'extends': 0.09; 'false.': 0.09; 'happen.': 0.09; 'implements': 0.09; 'logic': 0.09; 'oop': 0.09; 'override': 0.09; 'spreading': 0.09; 'try:': 0.09; 'type,': 0.09; 'wrapper': 0.09; '~ethan~': 0.09; 'python': 0.11; 'def': 0.12; 'creates': 0.14; 'thread': 0.14; '(true,': 0.16; '*do': 0.16; 'arbitrarily': 0.16; 'bool': 0.16; 'boolean': 0.16; 'c++)': 0.16; 'c/c++': 0.16; 'charles': 0.16; 'close:': 0.16; 'comparison.': 0.16; 'contract.': 0.16; 'correctness': 0.16; 'crude': 0.16; 'eliminating': 0.16; 'exist.': 0.16; 'false)': 0.16; "guido's": 0.16; 'happily': 0.16; 'instances,': 0.16; 'instantiated': 0.16; 'iterable': 0.16; 'iterables': 0.16; 'length,': 0.16; 'less,': 0.16; 'mainstream': 0.16; 'merely': 0.16; 'objection': 0.16; 'objects.': 0.16; 'operation,': 0.16; 'python;': 0.16; 'saying.': 0.16; 'semantics': 0.16; 'singleton': 0.16; 'subclass': 0.16; 'subclassing': 0.16; 'tuple': 0.16; 'tuple.': 0.16; 'exception': 0.16; 'prevent': 0.16; 'ignore': 0.16; 'language': 0.16; 'wrote:': 0.18; '(not': 0.18; 'do.': 0.18; 'trying': 0.19; 'written': 0.21; '(the': 0.22; '>>>': 0.22; 'memory': 0.22; 'example': 0.22; 'saying': 0.22; 'creating': 0.23; 'header:User-Agent:1': 0.23; '>>>': 0.24; 'controlling': 0.24; 'enhanced': 0.24; 'oriented': 0.24; 'passes': 0.24; 'proxy': 0.24; 'why.': 0.24; 'initial': 0.24; 'non': 0.24; 'versions': 0.24; "haven't": 0.24; "i've": 0.25; 'class.': 0.26; 'define': 0.26; 'equivalent': 0.26; 'holds': 0.26; 'mention': 0.26; 'nearly': 0.26; 'possibly': 0.26; 'second': 0.26; 'pass': 0.26; 'least': 0.26; 'skip:_ 20': 0.27; 'values': 0.27; 'header:In- Reply-To:1': 0.27; 'testing': 0.29; 'generally': 0.29; 'wonder': 0.29; "doesn't": 0.30; 'andrew': 0.30; 'compared': 0.30; 'converting': 0.30; 'newer': 0.30; 'restrict': 0.30; "i'm": 0.30; 'code': 0.31; '(perhaps': 0.31; 'apparently': 0.31; 'comparison': 0.31; 'operators': 0.31; 'proposing': 0.31; 'restricted': 0.31; 'tuples': 0.31; 'containing': 0.69; 'limit': 0.70; 'quality': 0.72; 'foreign': 0.74; 'acts': 0.74; 'goal': 0.75; 'objectives': 0.83; "'make'": 0.84; "'true'": 0.84; 'ethan': 0.84; 'furman': 0.84; 'huh?': 0.84; 'preventing': 0.84; 'technically': 0.84; 'url :python-dev': 0.84; 'canonical': 0.91; 'defeat': 0.91; 'do:': 0.91; 'reasoning': 0.91; 'received:173.201': 0.91; 'received:173.201.192': 0.91; 'write:': 0.91; 'besides,': 0.93; 'enhancement': 0.95 |
| Date | Mon, 12 Jan 2015 14:27:48 -0800 |
| From | Andrew Robinson <andrew3@r3dsolutions.com> |
| User-Agent | Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.0 |
| MIME-Version | 1.0 |
| To | python-list@python.org |
| Subject | Re: Comparisons and sorting of a numeric class.... |
| References | <54ABB88A.7070504@r3dsolutions.com> <54ABC52A.1050507@davea.name> <54ABE383.3020801@r3dsolutions.com> <CAPTjJmpktyHfghEr+cjPrhso7JgB4VfS4=5Gdi95gT0aFbSYGA@mail.gmail.com> <54AC97D9.4010504@r3dsolutions.com> <CAPTjJmooTK_+HVoeyeSrqBHN1=YjRYQ2kfDyQtL9JoA9SbTqsQ@mail.gmail.com> <54ACAA04.60801@r3dsolutions.com> <54ADC99F.3020405@stoneleaf.us> |
| In-Reply-To | <54ADC99F.3020405@stoneleaf.us> |
| Content-Type | multipart/alternative; boundary="------------030508070805080204060809" |
| X-BeenThere | python-list@python.org |
| X-Mailman-Version | 2.1.15 |
| Precedence | list |
| List-Id | General discussion list for the Python programming language <python-list.python.org> |
| List-Unsubscribe | <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe> |
| List-Archive | <http://mail.python.org/pipermail/python-list/> |
| List-Post | <mailto:python-list@python.org> |
| List-Help | <mailto:python-list-request@python.org?subject=help> |
| List-Subscribe | <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe> |
| Newsgroups | comp.lang.python |
| Message-ID | <mailman.17644.1421101760.18130.python-list@python.org> (permalink) |
| Lines | 410 |
| NNTP-Posting-Host | 2001:888:2000:d::a6 |
| X-Trace | 1421101760 news.xs4all.nl 2900 [2001:888:2000:d::a6]:40988 |
| X-Complaints-To | abuse@xs4all.nl |
| Xref | csiph.com comp.lang.python:83641 |
Show key headers only | View raw
[Multipart message — attachments visible in raw view] - view raw
On 01/07/2015 04:04 PM, Ethan Furman wrote:
> On 01/06/2015 07:37 PM, Andrew Robinson wrote:
>
>> Explain; How does mere subclassing of bool break the contract that bool has?
>> eg: What method or data would the superclass have that my subclass would not?
> bool's contract is that there are only two values (True and False) and only one instance each of those two values (True
> and False). If bool were subclassable, new values could be added with either completely different values (PartTrue) or
> with more of the same value (True, ReallyTrue, AbsolutelyTrue) -- hence, broken contract.
>
> --
> ~Ethan~
>
>
>
Huh? I'm not adding any values when I merely subclass bool ; and even if
the subclass could be instantiated -- that's doesn't mean a new value or
instance of the base class (bool) must exist. For I could happily work
with a new subclass that contains no new data, but only an already
_existing instance_ of 'True' or 'False_'_ as its value source. That
means there is no new value... but at most (and even that could be
worked around) a new instance of a subclass containing an existing
instance of it's base class.
Note: Guido only mentioned that he didn't want multiple instances of
the base class bool -- But that's not technically the same as objecting
to a subclass having an instance which CONTAINS an original bool
instance and not a new one.
There are other ways Guido could have modified the Python language to
prevent creation of new values without preventing the creation of a
subclass -- if that's what he was really after.... So -- no -- I
disagree with you.
Subclassing is allowed in many other OOP languages (not just C++) when
working with singletons, and dualtons, n-tons... and the very PURPOSE of
those objects is to prevent multiple instances, or spreading of
control. BUT -- Most object oriented languages I know of -- allow as
standard practice, subclassing of n-tons -- while (often) simultaneously
controlling or even eliminating the number of instances a subclass may
have / and or the values it may take. eg: depending on how flexible the
type/class definition of a language is -- languages handle sub-classing
of singletons differently.
Besides, a contract for a class can only be assumed to be valid for code
designed for that specific class -- not code made for a subclass; The
contract for bool simply says nothing about programs designed for any
other classes that bool is found inside of -- either as a subclass or a
subelement; eg: I can still put bool inside another object with
different methods: eg: I just write: (False,) as proof -- so Guido
couldn't possibly have been trying to limit the methods which can
operate on bool or the number of links to bool.
So I don't understand why Guido cared to restrict subclassing of bool --
and what the contract you mention has to do with it -- eg: what was his
actual goal ? Was it memory conservation, or compatability of built-in
return types -- or what ? There is no written 'contract' saying exactly
what Guido's design objectives were in detail and more importantly
'WHY'; but Guido only said that subclassing instances allowed a 'back
door' (not that subclassiing itself was bad, just that it allowed some
side effect...) to whatever Guido really didn't want to happen.
Python generally allows subclassing of singleton instances; so that
makes 'bool' is an arbitrary exception to the general rule which Guido
decided to make... and he did so without any very clear explanation as
to why. eg: he cited what C/C++ *must *do as part of his reasoning --
but C/C++ can apparently do something that Guido thought it couldn't
(Guido was flat wrong).... and for that reason, I really wonder if
Guido's decision was some kind of spur of the moment erroneous epiphany
-- bolstered by the fact that he said "I realized last night..." like
something he had never thought of before, or thought through carefully....
https://mail.python.org/pipermail/python-dev/2002-March/020822.html
And worse, Guido's problem even apparently extends to making 'duck
types' which other writers in this thread have been proposing I do. eg:
They, too, are going against canonical Guido's epiphany night...
Of course, you can define your own subclass of int similar to the bool
class I show in the PEP, and you can give it any semantics you want --
but that_would also defeat the purpose of having a standard bool_.
Not to mention, that Charles Bool's two initial values True and False
are NOT the only ones used in computer engineering and science; for
boolean logic only became useful at a time when engineers and
mathematicians realized that at least a third type, AKA: 'Don't care' --
was necessary for doing correctness testing of logic in a tractable
way. So -- Guido arbitrarily chose to make bool based on a historical
curiosity that never has been mainstream in logic analysis. eg: He
based it on a beta quality revision of boolean theory.... Look at any
logic design and testing package -- such as silos Three, or verilog, or
VHDL, UHDL, etc. and all of them support tri-state logic with at least
one 'don't care' state for boolean logic.
But setting that all aside....
I've already said that I don't actually need an instance of the
subclass... but you (and others) repeatedly ignore what I'm saying. So,
let me try to give a crude example of alternative routes an OOP language
like Python COULD take....
Consider -- There are generic alternatives to class instances in many
OOP languages; eg: making proxy or wrapper objects.
These are not foreign ideas in Python; though it implements them too
crudely for my use or else there is a trick to the Python versions I
haven't figured out yet -- but none the less, Python already creates
proxy objects ( CF: super() ) ; so it's not a foreign idea.
For my purposes; At minimum I need a wrapper and proxy object (both)
which can be passed in lieu of a an actual bool or subclass of bool; eg:
it holds an actual False or True object (the super), and can pass the
test whenever a user attempts an 'isinstance( mybinding, bool )' for
type checking; but fails whenever it is examined by 'is' True or 'is'
False; Python can almost do what I want -- but not quite -- because the
existing proxys are not quite as transparent as they need to be; but
it's very close:
>>> a=super(True,int)
>>> isinstance( a.__self__, bool )
True
>>> a is bool
False
So -- since it can't be done, the next best thing is some kind of
wrapper object acting as a proxy;
As a first attempt -- I'll override the comparison operators in a
generic way to 'make' a more generic proxy:
def _op(op,other): # Call an operation, insuring iterable is second arg.
try: other[0]
except: return op((other,))
return op(other)
class ETuple(tuple):
"""
Enhanced Tuple.
A tuple which does rich comparisons even when the item being
compared against is not an iterable by converting non iterables to
tuples of length, exactly one.
"""
def __new__(cls, data):return super(ETuple,cls).__new__(cls,data)
def __eq__(self,other):return _op(super(ETuple,self).__eq__,other)
def __ne__(self,other):return _op(super(ETuple,self).__ne__,other)
def __lt__(self,other):return _op(super(ETuple,self).__lt__,other)
def __le__(self,other):return _op(super(ETuple,self).__le__,other)
def __gt__(self,other):return _op(super(ETuple,self).__gt__,other)
def __ge__(self,other):return _op(super(ETuple,self).__ge__,other)
def __cmp__(self,other):return _op(super(ETuple,self).__cmp__,other)
def __nonzero__(self,other):return
_op(super(ETuple,self).__cmp__,other)
Now, I can do:
>>> (False,) == False
True
and:
>>> (False,) is False
False
>>> PartFalse = (False,)
>>> PartFalse == False
True
>>> PartFalse == PartTrue
False
and, it's clear that I am not creating a new instance of 'bool;' -- for
PartFalse is not a new instance of bool, it is (under rich comparison),
exactly equivalent to a bool. eg: a duck type under rich comparison.
Therefore, RBool acts exactly like a bool for traditional code in a
nearly transparent way (proxy idea) -- but still allows detection of the
wrapper by 'is' so that newer code can take advantage of a refined
definition of falseness...
So, If Etuple was a subclass of 'bool', instead of just tuple -- and
was restricted to wrap ONLY an existing bool (perhaps as an enhancement
to the class definition...) -- it would achieve all my design goals; so
your objection that it is a new value would simply be false. It would
merely be a wrapper of an existing bool that passes the type check
isinstance( bool, ETuple(False) ) --> True .
Why was it so important to Guido to make this impossible???
Back to comp.lang.python | Previous | Next | Find similar | Unroll thread
Re: Comparisons and sorting of a numeric class.... Andrew Robinson <andrew3@r3dsolutions.com> - 2015-01-12 14:27 -0800
csiph-web