Issue19988
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2013-12-15 16:27 by ethan.furman, last changed 2022-04-11 14:57 by admin. This issue is now closed.
Messages (10) | |||
---|---|---|---|
msg206238 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2013-12-15 16:27 | |
In Py3k __hex__ and __oct__ were removed, and hex() and oct() switched to use __index__. hex() and oct() should be using __int__ instead. Having read through PEP 357 [1] I see that __index__ is /primarily/ concerned with allowing arbitrary objects to be used in slices, but will also allow Python to convert an object to an int "whenever it needs one". The problem is that my dbf [2] module has a couple custom types (Logical and Quantum) that allow for ternary logic (False/True/Unknown). As much as possible Logical is intended to be a drop in replacement for the bool type, but of course there are some differences: - internally 'unknown' is represented as None - attempts to get an int, float, complex, etc., numeric value on Unknown raises an Exception - attempts to get the numeric string value via __hex__ and __oct__ on Unknown raises an Exception - when Unknown is used as an index (via __index__), 2 is returned The problem, of course, is that in Python 3 calling hex() and oct() on Unknown now succeeds when it should be raising an exception, and would be if __int__ were used instead of __index__. In summary, if Python just switches to using __index__, there would be little point in having separate __int__ and __index__ methods. [1] http://www.python.org/dev/peps/pep-0357 [2] https://pypi.python.org/pypi/dbf |
|||
msg206241 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2013-12-15 17:05 | |
__index__() is used because float has __int__ but not __index__. >>> (42.0).__int__() 42 >>> (42.0).__index__() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'float' object has no attribute '__index__' |
|||
msg206245 - (view) | Author: Antoine Pitrou (pitrou) * ![]() |
Date: 2013-12-15 17:28 | |
Indeed, the definition and use of __index__ has derived since PEP 357. Nowadays, __index__ means "can be converted to an int without loss". In any case, I find the behaviour of your "logical type" a bit dubious. If it's like bool but ternary, it *should* convert to int (or perhaps be an int subclass like bool). |
|||
msg206255 - (view) | Author: Mark Dickinson (mark.dickinson) * ![]() |
Date: 2013-12-15 20:45 | |
> hex() and oct() should be using __int__ instead. Strong -1 from me. I wouldn't want `hex(45.3)` to work, and `hex(45.0)` working isn't much better. |
|||
msg206256 - (view) | Author: Stefan Krah (skrah) * ![]() |
Date: 2013-12-15 20:57 | |
-1 from me as well. I would not want to audit a large program for accidentally converted floats. |
|||
msg206261 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2013-12-15 21:25 | |
Guido, I believe that __index__ was your initiative. Do you care to opine on this one? |
|||
msg206263 - (view) | Author: Guido van Rossum (gvanrossum) * ![]() |
Date: 2013-12-15 22:50 | |
I agree with Mark and Stafan. Hex/oct/bin are only defined for integers. __int__ is ambiguous -- it has the same problem as (int) in C in that it applies to floats and then loses the fraction. I think the problem with Ethan's ternary logic is that it tries to act as an index and yet doesn't want to be an integer -- that doesn't make a lot of logical sense. (You should use a dict to map from true/false/unknown, not a list of size three.) |
|||
msg206275 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2013-12-16 02:04 | |
For the record, the true/false values of my Logical type do convert to int, just not the unknown value. I agree using __int__ is dubious because of float (and Decimal, etc.), which means really the only clean way to solve the issue (definitely for me, and for any one else in a similar situation) is to bring back __hex__, __oct__, and, presumably, __bin__. To make things even worse, there is a discrepancy between hex() and %x, oct() and %o: --> hex(Unknown) '0x2' --> oct(Unknown) '0o2' --> '%x' % Unknown Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: %x format: a number is required, not Logical --> '%o' % Unknown Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: %o format: a number is required, not Logical Which is bizarre when one considers: --> '%o' % Truth '1' So if '%o' fails, why doesn't oct()? Do we reopen this issue, or start a new one? |
|||
msg206277 - (view) | Author: Guido van Rossum (gvanrossum) * ![]() |
Date: 2013-12-16 04:38 | |
I still think the problem is with your class design. You shouldn't want a hex representation for a value that's not an integer. For the difference between %x and hex() please open another issue (you might want to track down the cause in the source first so you can add a patch or at least a suggested fix to the issue). |
|||
msg206291 - (view) | Author: Ethan Furman (ethan.furman) * ![]() |
Date: 2013-12-16 10:33 | |
Guido van Rossum opined: ------------------------ > I still think the problem is with your class design. > You shouldn't want a hex representation for a value > that's not an integer. Well, in fairness I only supported it because bool does, and I was trying to have Logical match bool as closely as possible. Which is also why, in Py2, attempting such operations on an Unknown value raises exceptions. As an example: # bool --> True + True 2 # Logical --> Truth + Truth 2 --> Truth + Unknown Logical('?') I can do that because I was able to override __add__ and __raddd__; however, if I _do not_ overide index: # bool --> ['no', 'yes'][True] 'yes' # Logical --> ['no', 'yes', 'maybe'][Truth] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: list indices must be integers, not Logical So either I break compatibility with bools in a rather fundamental way, or I live with the eyesore of being able to use %x and %o on Unknown values. Incidentally, bool is still not subclassable, and using int as a base class for Logical blew up over half my tests. Perhaps not quite so incidentally, if __index__ is added to an Enum (not IntEnum) subclass, it will have the same wierdness. Guido van Rossum stated: ------------------------ > For the difference between %x and hex() please open another > issue (you might want to track down the cause in the source > first so you can add a patch or at least a suggested fix to > the issue). Issue19995 is created, current participants nosied. I'll track it down as soon as I can (may be a few days). |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:57:55 | admin | set | github: 64187 |
2013-12-16 10:33:23 | ethan.furman | set | messages: + msg206291 |
2013-12-16 04:38:51 | gvanrossum | set | messages: + msg206277 |
2013-12-16 02:04:56 | ethan.furman | set | messages: + msg206275 |
2013-12-15 22:50:45 | gvanrossum | set | status: open -> closed resolution: rejected messages: + msg206263 stage: resolved |
2013-12-15 21:25:09 | rhettinger | set | assignee: gvanrossum messages: + msg206261 nosy: + rhettinger, gvanrossum |
2013-12-15 20:57:26 | skrah | set | nosy:
+ skrah messages: + msg206256 |
2013-12-15 20:45:05 | mark.dickinson | set | messages: + msg206255 |
2013-12-15 17:28:32 | pitrou | set | nosy:
+ pitrou messages: + msg206245 |
2013-12-15 17:05:27 | serhiy.storchaka | set | nosy:
+ mark.dickinson, serhiy.storchaka messages: + msg206241 |
2013-12-15 16:27:52 | ethan.furman | create |