Subclasses vs. special methods
Should implicit converting an instance of int, float, complex, str, bytes, etc subclasses to call appropriate special method __int__ (or __index__), __float__, __complex__, __str__, __bytes__, etc? Currently explicit converting calls these methods, but implicit converting doesn't.
class I(int): ... def __int__(self): return 42 ... def __index__(self): return 43 ... class F(float): ... def __float__(self): return 42.0 ... class S(str): ... def __str__(self): return '*' ... int(I(65)) 42 float(F(65)) 42.0 str(S('A')) '*' chr(I(65)) 'A' import cmath; cmath.rect(F(65), 0) (65+0j) ord(S('A')) 65
Issue17576 [1] proposes to call special methods for implicit converting. I have doubts about this. 1. I afraid that this will adds places where arbitrary Python code is unexpectedly called. For example see changeset9a61be172c23 discussed in neighbor thread. If the "k" format code will call __int__(), Python code can modify unpacked list argument during parsing arguments in PyArg_ParseTuple(). 2. PyLong_As*() functions already is not very consistent. Some of them calls __int__() for argument which is not an instance of int subclass, other accepts only instances of int subclasses. PyLong_AsVoidPtr() calls or not calls __int__() depending on the sign of the argument. 3. We can't consistency call special methods for all types. E.g. for strings we can't call __str__() when processing the "s" code in PyArg_ParseTuple() because this will cause a leak. I think that overriding special converting method in a subclass of corresponding type should be restricted. I see two consistent and safe possibilities: 1. Forbidden. I.e. above declarations of I, F and S classes should raise exceptions. 2. Has no effect. I.e. both int(I(65)) and operator.index(I(65)) should return 65. [1] http://bugs.python.org/issue17576
On 04.01.14 13:58, Serhiy Storchaka wrote:
Should implicit converting an instance of int, float, complex, str, bytes, etc subclasses to call appropriate special method __int__ (or __index__), __float__, __complex__, __str__, __bytes__, etc? Currently explicit converting calls these methods, but implicit converting doesn't.
class I(int): ... def __int__(self): return 42 ... def __index__(self): return 43 ... class F(float): ... def __float__(self): return 42.0 ... class S(str): ... def __str__(self): return '*' ... int(I(65)) 42 float(F(65)) 42.0 str(S('A')) '*' chr(I(65)) 'A' import cmath; cmath.rect(F(65), 0) (65+0j) ord(S('A')) 65
Issue17576 [1] proposes to call special methods for implicit converting. I have doubts about this.
Note that for explicit conversion this was implemented a long time ago. See this ancient thread about str/unicode subclasses and __str__/__unicode__: https://mail.python.org/pipermail/python-dev/2005-January/051175.html And this bug report: http://bugs.python.org/issue1109424
[...]
Servus, Walter
participants (2)
-
Serhiy Storchaka
-
Walter Dörwald