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 2018年03月05日 21:07 by josh.r, last changed 2022年04月11日 14:58 by admin. This issue is now closed.
| Messages (5) | |||
|---|---|---|---|
| msg313285 - (view) | Author: Josh Rosenberg (josh.r) * (Python triager) | Date: 2018年03月05日 21:07 | |
In Python 2, making a user-defined class support formatting using the integer-specific type codes required that __int__ be defined and nothing else (that is, '%x' % Foo() only required Foo to provide a __int__ method). In Python 3, this was changed to perform the conversion via __index__ for the %o, %x and %X format types (to match how oct and hex behave), not __int__, but the pre-check for validity in unicodeobject.c's mainformatlong function is still based on PyNumber_Check, not PyIndex_Check, and PyNumber_Check is concerned solely with __int__ and __float__, not __index__. This means that a class with __index__ but not __int__ can't be used with the %o/%x/%X format codes (even though hex(mytype) and oct(mytype) work just fine). It seems to me that either: 1. PyNumber_Check should be a superset of PyIndex_Check (broader change, probably out of scope) or 2. mainformatlong should restrict the scope of the PyNumber_Check test to only being used for the non-'o'/'x'/'X' tests (where it's needed to avoid coercing strings and the like to integer). Change #2 should be safe, with no major side-effects; since PyLong and subclasses always passed the existing PyNumber_Check test anyway, and PyNumber_Index already performs PyIndex_Check, the only path that needs PyNumber_Check is the one that ends in calling PyNumber_Long. |
|||
| msg313286 - (view) | Author: Josh Rosenberg (josh.r) * (Python triager) | Date: 2018年03月05日 21:13 | |
Note: Obviously, defining __index__ without defining __int__ is a little strange (it's *equivalent* to int, but can't be *coerced* to int?), so yet another fix would be addressing #20092 so it wouldn't be possible for a type to define __index__ without (implicitly) defining __int__. |
|||
| msg313288 - (view) | Author: Josh Rosenberg (josh.r) * (Python triager) | Date: 2018年03月05日 21:29 | |
To be clear, this is a problem with old-style (printf-style) formatting, and applies to both bytes formatting and str formatting. So a class like: class Foo: def __index__(self): return 1 will fail with a TypeError should you do any of: '%o' % Foo() '%x' % Foo() '%X' % Foo() b'%o' % Foo() b'%x' % Foo() b'%X' % Foo() even though hex(Foo()) and oct(Foo()) work without issue. |
|||
| msg313311 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2018年03月06日 08:32 | |
Agreed that this seems wrong. |
|||
| msg337928 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) | Date: 2019年03月14日 14:58 | |
Resolved in issue36048. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:58 | admin | set | github: 77183 |
| 2019年03月14日 14:58:36 | serhiy.storchaka | set | status: open -> closed superseder: Deprecate implicit truncating when convert Python numbers to C integers: use __index__, not __int__ nosy: + serhiy.storchaka messages: + msg337928 resolution: duplicate stage: resolved |
| 2018年09月23日 14:51:05 | xtreak | set | nosy:
+ xtreak |
| 2018年03月06日 08:32:13 | mark.dickinson | set | nosy:
+ mark.dickinson, eric.smith messages: + msg313311 |
| 2018年03月05日 21:29:44 | josh.r | set | messages:
+ msg313288 title: Making a class formattable as hex/oct integer requires both __int__ and __index__ for no good reason -> Making a class formattable as hex/oct integer with printf-style formatting requires both __int__ and __index__ for no good reason |
| 2018年03月05日 21:13:32 | josh.r | set | messages: + msg313286 |
| 2018年03月05日 21:07:14 | josh.r | create | |