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 2016年05月12日 07:15 by serhiy.storchaka, last changed 2022年04月11日 14:58 by admin. This issue is now closed.
| Messages (6) | |||
|---|---|---|---|
| msg265368 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) | Date: 2016年05月12日 07:15 | |
Python implementation of Decimal.from_float() calls __new__ and __init__ methods of subclass.
>>> from _pydecimal import Decimal
>>> class D(Decimal):
... def __new__(cls, *args, **kwargs):
... print('__new__')
... return Decimal.__new__(cls, *args, **kwargs)
... def __init__(self, *args, **kwargs):
... print('__init__')
...
>>> print(type(D.from_float(42)))
__new__
__init__
<class '__main__.D'>
>>> print(type(D.from_float(42.0)))
__new__
__init__
<class '__main__.D'>
But C implementation doesn't.
>>> from decimal import Decimal
>>> class D(Decimal):
... def __new__(cls, *args, **kwargs):
... print('__new__')
... return Decimal.__new__(cls, *args, **kwargs)
... def __init__(self, *args, **kwargs):
... print('__init__')
...
>>> print(type(D.from_float(42)))
<class '__main__.D'>
>>> print(type(D.from_float(42.0)))
<class '__main__.D'>
This means that resulting instance of Decimal subclass can be in not valid state.
Example is Decimal enums (see also issue23640).
>>> from decimal import Decimal
>>> from enum import Enum
>>> class D(Decimal, Enum):
... A = Decimal('3.25')
...
>>> D(Decimal(3.25))
<D.A: Decimal('3.25')>
>>> D(3.25)
<D.A: Decimal('3.25')>
>>> D.from_float(3.25)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/serhiy/py/cpython/Lib/enum.py", line 486, in __repr__
self.__class__.__name__, self._name_, self._value_)
AttributeError: 'D' object has no attribute '_name_'
A solution is to reproduce Python implementation in C code:
result = ... # create exact Decimal
if cls is not Decimal:
result = cls(result)
return result
|
|||
| msg268889 - (view) | Author: Roundup Robot (python-dev) (Python triager) | Date: 2016年06月20日 10:11 | |
New changeset dd3f48f1df86 by Stefan Krah in branch '3.5': Issue #27006: from_float(): call the subclass' __new__() and __init__(). https://hg.python.org/cpython/rev/dd3f48f1df86 |
|||
| msg268890 - (view) | Author: Stefan Krah (skrah) * (Python committer) | Date: 2016年06月20日 10:32 | |
Thank you for the detailed summary! |
|||
| msg268892 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) | Date: 2016年06月20日 11:27 | |
PyDec_CheckExact(type) always return 0. Should be PyDec_CheckExact(result). And what about other calls of PyDecType_FromFloatExact()? Can they produce broken instance of Decimal subtype? |
|||
| msg268896 - (view) | Author: Roundup Robot (python-dev) (Python triager) | Date: 2016年06月20日 12:13 | |
New changeset 51a7a97c3ed4 by Stefan Krah in branch '3.5': Issue #27006: Do not use PyDec_CheckExact() on a type. https://hg.python.org/cpython/rev/51a7a97c3ed4 |
|||
| msg268898 - (view) | Author: Stefan Krah (skrah) * (Python committer) | Date: 2016年06月20日 12:22 | |
> PyDec_CheckExact(type) always return 0. Should be PyDec_CheckExact(result). 'result' is always an exact decimal, because your enum example won't work otherwise. > And what about other calls of PyDecType_FromFloatExact()? Can they produce broken instance of Decimal subtype? The PyDecType* functions handle calling the correct allocator, they don't handle calling __new__(). Why should they? The regular non-class-method enum examples worked. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:30 | admin | set | github: 71193 |
| 2016年06月20日 12:58:32 | skrah | set | status: open -> closed |
| 2016年06月20日 12:22:33 | skrah | set | messages: + msg268898 |
| 2016年06月20日 12:13:58 | python-dev | set | messages: + msg268896 |
| 2016年06月20日 11:27:13 | serhiy.storchaka | set | status: closed -> open messages: + msg268892 |
| 2016年06月20日 10:32:21 | skrah | set | status: open -> closed resolution: fixed messages: + msg268890 stage: resolved |
| 2016年06月20日 10:11:28 | python-dev | set | nosy:
+ python-dev messages: + msg268889 |
| 2016年05月12日 07:15:44 | serhiy.storchaka | create | |