Movatterモバイル変換


[0]ホーム

URL:


[Python-Dev] int() and math.trunc don't accept objects that only define __index__

Rémi Lapeyreremi.lapeyre at henki.fr
Wed Mar 13 06:21:31 EDT 2019


Le 22 février 2019 à 18:14:01, Nick Coghlan(ncoghlan at gmail.com(mailto:ncoghlan at gmail.com)) a écrit:> On Fri, 22 Feb 2019 at 18:29, Serhiy Storchaka wrote:> > Should we add default implementations of __float__ and __complex__ when> > either __index__ or __int__ is defined? Currently:> >> > >>> class A:> > ... def __int__(self): return 42> > ...> > >>> int(A())> > 42> > >>> float(A())> > Traceback (most recent call last):> > File "", line 1, in> > TypeError: float() argument must be a string or a number, not 'A'> > >>> complex(A())> > Traceback (most recent call last):> > File "", line 1, in> > TypeError: complex() first argument must be a string or a number, not 'A'> >> > Or just document that in order to have a coherent integer type class,> > when __index__() or __int__() are defined __float__() and __complex__()> > should also be defined, and all should return equal values.>> I think when __index__ is defined, it would be reasonable to have that> imply the same floating point conversion rules as are applied for> builtin ints, since the conversion is supposed to be lossless in that> case (and if it isn't lossless, that's what `__int__` is for).> However, I don't think the decision is quite as clearcut as it is for> `__index__` implying `__int__`.When __index__ is defined it means that there is a lossless conversionto int possible. In this case, this means a lossless conversion tofloat and complex is also possible (with the exception of overflowsbut anyone doing float(var) should expect them). In this case, I thinkdefining __index__ could set a default for __int__, __float__ and__complex__.> Lossy conversions to int shouldn't imply anything about conversions to> real numbers or floating point values.I think the right behavior is the other way around, it should go theother way around from a superset to a subset, when __int__ is defined__float__ should not have a default set because there might be abetter default than float(int(self)), but when __float__ is defined,it should be safe to make __int__ default to int(float(self)) if notdefined.This would simplify this behavior:Python 3.7.2 (default, Jan 13 2019, 12:50:01)[Clang 10.0.0 (clang-1000.11.45.5)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> class Test:...     def __float__(self):...             return 3.14...>>> float(Test())3.14>>> int(float(Test()))3>>> int(Test())Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: int() argument must be a string, a bytes-like object or anumber, not ‘Test'Defining __complex__ shouldn’t do anything since they have one moredimension there is no clear way to convert to ints and floats which isalready the behavior of the the builtin complex type:>>> int(complex())Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: can't convert complex to int>>> float(complex())Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: can't convert complex to floatHere’s an implementation of what I’m thinking of:>>> def finish_class(cls):...     def set(cls, name, target):...         if not hasattr(cls, name):...             setattr(cls, name, target)......     if hasattr(cls, '__index__'):...         set(cls, '__int__', cls.__index__)...         set(cls, '__float__', lambda self: float(self.__index__()))...         set(cls, '__complex__', lambda self: complex(self.__index__(), 0))...     if hasattr(cls, '__float__'):...         set(cls, '__int__', lambda self: int(float(self)))...>>>>>> class Test:...     def __index__(self):...         return 4...>>> finish_class(Test)>>>>>> int(Test())4>>> float(Test())4.0>>> complex(Test())(4+0j)>>>>>> class Test2:...     def __float__(self):...         return 3.14...>>> finish_class(Test2)>>>>>> int(Test2())3>>> float(Test2())3.14


More information about the Python-Devmailing list

[8]ページ先頭

©2009-2025 Movatter.jp