Re: [Python-Dev] Semantics of __int__(), __index__()
On 4/4/2013 10:04 PM, Steven D'Aprano wrote: When I call int(), I'm expecting an int. We agree so far..., That includes well-behaved subclasses of int that continue to behave like ints in all the ways that matter. but not here. I currently expect an actual int instance for 3 reasons. 1. As I read the doc, that is the currently documented 'should'. 2. I believe class constructors should, generally, return an instance of the class, in the narrow sense, and that factory functions should, generally, be used to return instances of multiple classes. The multiple classes would typically, or at least often, all be subclasses of some baseclass. 3. Most apropos to your next paragraph: *because* Python is duck-typed, I would not replace a function arg that might be an int subclass with int(arg) unless (I thought) the difference would make a difference. Lets consider cases: 1. int(non-scalar-number): this is usually an error, except for bytes or unicode strings that represents a number in standard base-[2-32] notation. int has builtin knowledge of these two builtin classes. One can add an __int__ method to string subclasses that represent integers with non-standard notation. A common use is int(input(prompt)) or int(other-external-input). 2. int(rational): for floats, Fractions, and Decimals, this returns the integral part, truncating toward 0. Decimal and float have __int__ methods. Fractions, to my surprise, does not, so int must use __floor__ or __round__ as a backup. I believe we have no disagreement that int() should return an int for these cases. Here is a possible use for input checking. def fib(n): return fibonnaci(integral input); return type == input type if int(n) != n or n 0: raise TypeError('fib input must be a count') # let int() or exception propagate # the input check is needed to prevent infinite looping calculate with input n return fib-of-n Because of duck-typing, there is no need to replace n with int(n). The return type will be the input type. 3. int(int-subclass-instance): If the int subclass instances behave like an int in all ways that matter in the context, there is no reason to specifically do. In other words, this use should be very rare, such as wanting the int repr. I am also not sure, without checking the doc for the definition of the bit operations, if all int subclasses would dependably substitute in bit manipulations. So unless you can give a good reason otherwise, I think the subclass .__int__ class should assume that the programmer might actually specifically want an int instance. In the example above, int() is part of a general case 2 input check that non-negative subclass instances should pass whether they return themselves or an int. It's curious to see the (d)evolution of thinking on type checking in Python circles. Once upon a time, type checking was discouraged, duck-typing was encouraged, and the philosophy was that an int is anything that behaves like an int. I always differentiated 'int' as a type/class int object from 'integer' as anything that behaves like an 'int'. For me, and the function outlined above, that includes integer-values rationals along with int subclass instances. Now type-checking is tolerated or even encouraged, provided that you use isinstance, I seem to have missed the encouragement. and an int is anything that inherits from the builtin (or the ABC). And this proposed change in behaviour To conform to how come read the doc.. continues the move away from Python's former emphasis on duck-typing. For the reason explained above, I do not see this issue in such apocalyptic terms ;-) -- Terry Jan Reedy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Fri, Apr 5, 2013 at 6:34 PM, Terry Jan Reedy tjre...@udel.edu wrote: 2. int(rational): for floats, Fractions, and Decimals, this returns the integral part, truncating toward 0. Decimal and float have __int__ methods. Fractions, to my surprise, does not, so int must use __floor__ or __round__ as a backup. It uses __trunc__, which is supposed to be the unambiguous Yes I really want to throw away the fractional part and risk losing information replacement for __int__. int() will try __int__ first, and then __trunc__, as per PEP 3141. Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
Guido van Rossum, 04.04.2013 23:14: On Thu, Apr 4, 2013 at 1:50 PM, Tim Delaney wrote: I fall into: 1. int(), float(), str() etc should return that exact class (and operator.index() should return exactly an int). 2. It could sometimes be useful for __int__() and __index__() to return a subclass of int. So, for the int constructor, I would have the following logic (assume appropriate try/catch): def __new__(cls, obj): i = obj.__int__() if type(i) is int: return i return i._internal_value CPython can solve this in C using an unsafe cast, and the code that checks for allowable subclasses of int actually ensures such a cast will work. But it still feels wrong; __int__ should be expected to do the work. +1, that's why it's called __int__ (even if it returns a PyLong in Py3 ;) Stefan ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
Eric Snow: On Wed, Apr 3, 2013 at 6:47 AM, Hrvoje Niksic hrvoje.nik...@avl.com wrote: It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. Unless you want to try to use the concrete C-API in CPython. In my experience the concrete API is not very subclass friendly. Nick: Using it with subclasses is an outright bug (except as part of a subclass implementation). This is true for mutable objects like dicts and lists where calling things like PyDict_SetItem will happily circumvent the object. But for ints and floats, all that the C code really cares about is the object's intrinsic value as returned by PyLong_AS_LONG and friends, which is constant and unchangeable by subclasses. The typical reason to subclass int is to add more information or new methods on the instance, not to break basic arithmetic. Doing anything else breaks subtitutability and is well outside the realm of consenting adults. Someone who wants to change basic arithmetic is free to implement an independent int type. Hrvoje ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 4 April 2013 10:39, Hrvoje Niksic hrvoje.nik...@avl.com wrote: On Wed, Apr 3, 2013 at 6:47 AM, Hrvoje Niksic hrvoje.nik...@avl.com wrote: It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. [SNIP] The typical reason to subclass int is to add more information or new methods on the instance, not to break basic arithmetic. Doing anything else breaks subtitutability and is well outside the realm of consenting adults. Someone who wants to change basic arithmetic is free to implement an independent int type. The reason for calling int(obj) is to get an object that is precisely of type int. When I call this I do not want any modified or additional methods or data attached to the resulting object. The example given at the start of the thread makes minimal modifications in an int subclass but still allows the result of int(obj) to be unpickleable: class Int1(int): ... def __int__(self): ... return self ... n = Int1(4) n 4 import pickle ni = int(n) pickle.dumps(ni) ... snip ... File q:\tools\Python27\lib\pickle.py, line 562, in save_tuple save(element) File q:\tools\Python27\lib\pickle.py, line 331, in save self.save_reduce(obj=obj, *rv) File q:\tools\Python27\lib\pickle.py, line 401, in save_reduce save(args) File q:\tools\Python27\lib\pickle.py, line 286, in save f(self, obj) # Call unbound method with explicit self File q:\tools\Python27\lib\pickle.py, line 562, in save_tuple save(element) File q:\tools\Python27\lib\pickle.py, line 291, in save issc = issubclass(t, TypeType) RuntimeError: maximum recursion depth exceeded while calling a Python object I don't know whether that's a bug in pickle, but I think it's fair to say that there are times when someone wants an object that is precisely of type int. They should be able to rely on int(obj) returning an int or raising an error. This is true similarly for __index__. The entire purpose of __index__ is to permit APIs like list.__getitem__ to work extensibly with any int-like object. This is achieved by allowing any object to advertise its convertibility from an int-like object to an int with the same numeric value. Anyone who calls operator.index(obj) is explicitly stating that they do not want any property of obj apart from its integer value and that they want that as an int. That it should be an object of type int is explicitly stated in PEP 357 (http://www.python.org/dev/peps/pep-0357/): 2) The __index__ special method will have the signature def __index__(self): return obj where obj must be either an int or a long. Oscar ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Fri, Apr 5, 2013 at 1:23 AM, Oscar Benjamin oscar.j.benja...@gmail.com wrote: The reason for calling int(obj) is to get an object that is precisely of type int. When I call this I do not want any modified or additional methods or data attached to the resulting object. There's something I'm fundamentally not understanding about this debate, and that is: How is it that calling a class can logically return anything other than an instance of that class? Taking it to a user-defined type: class Foo: pass class Bar(Foo): pass Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? ChrisA ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
Am 04.04.2013 16:47, schrieb Chris Angelico: On Fri, Apr 5, 2013 at 1:23 AM, Oscar Benjamin oscar.j.benja...@gmail.com wrote: The reason for calling int(obj) is to get an object that is precisely of type int. When I call this I do not want any modified or additional methods or data attached to the resulting object. There's something I'm fundamentally not understanding about this debate, and that is: How is it that calling a class can logically return anything other than an instance of that class? Taking it to a user-defined type: class Foo: pass class Bar(Foo): pass Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? I think the issue that the constructors for basic classes like int() are often seen as built-in functions that cast values to the respective type (or alternatively, functions that call the respective __method__ on the argument, like len()), not class constructors. FWIW, I agree with you that the class constructor view is the right one and would prefer exact int/str/... instances returned. Georg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: On Fri, Apr 5, 2013 at 1:23 AM, Oscar Benjamin oscar.j.benja...@gmail.com wrote: The reason for calling int(obj) is to get an object that is precisely of type int. When I call this I do not want any modified or additional methods or data attached to the resulting object. There's something I'm fundamentally not understanding about this debate, and that is: How is it that calling a class can logically return anything other than an instance of that class? Taking it to a user-defined type: class Foo: pass class Bar(Foo): pass Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): class C: ... def __new__(cls): return 42 ... C() 42 -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 2013-04-04, at 16:47 , Chris Angelico wrote: Sure, I could override __new__ to do stupid things Or to do perfectly logical and sensible things, such as implementing cluster classes or using the base class as a factory of sorts. in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. The problem is the expectation of what a Foo object is: type-wise, any Bar object is also a Foo object. I would not expect Foo() to return an object of a completely unrelated type, but returning an object of a subtype? That does not seem outlandish. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Fri, Apr 5, 2013 at 1:59 AM, Guido van Rossum gu...@python.org wrote: On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): Right, I'm aware it's possible. But who would expect it of a class? ChrisA ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 2013-04-04, at 17:01 , Chris Angelico wrote: On Fri, Apr 5, 2013 at 1:59 AM, Guido van Rossum gu...@python.org wrote: On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): Right, I'm aware it's possible. But who would expect it of a class? Given it's one of the use cases for __new__ and immutable types have to be initialized through __new__ anyway, why would it be unexpected? ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Thu, Apr 4, 2013 at 8:01 AM, Chris Angelico ros...@gmail.com wrote: On Fri, Apr 5, 2013 at 1:59 AM, Guido van Rossum gu...@python.org wrote: On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): Right, I'm aware it's possible. But who would expect it of a class? If it's documented you could expect it. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
Le Fri, 5 Apr 2013 01:47:45 +1100, Chris Angelico ros...@gmail.com a écrit : class Foo: pass class Bar(Foo): pass Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. OSError(errno.ENOENT, couldn't find that file) FileNotFoundError(2, couldn't find that file) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/04/2013 08:01 AM, Chris Angelico wrote: On Fri, Apr 5, 2013 at 1:59 AM, Guido van Rossum gu...@python.org wrote: On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): Right, I'm aware it's possible. But who would expect it of a class? FTR I'm in the int() should return an int camp, but to answer your question: my dbf module has a Table class, but it returns either a Db3Table, FpTable, VfpTable, or ClpTable depending on arguments (if creating a new one) or the type of the table in the existing dbf file. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 5 April 2013 02:16, Ethan Furman et...@stoneleaf.us wrote: On 04/04/2013 08:01 AM, Chris Angelico wrote: On Fri, Apr 5, 2013 at 1:59 AM, Guido van Rossum gu...@python.org wrote: On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): Right, I'm aware it's possible. But who would expect it of a class? FTR I'm in the int() should return an int camp, but to answer your question: my dbf module has a Table class, but it returns either a Db3Table, FpTable, VfpTable, or ClpTable depending on arguments (if creating a new one) or the type of the table in the existing dbf file. I fall into: 1. int(), float(), str() etc should return that exact class (and operator.index() should return exactly an int). 2. It could sometimes be useful for __int__() and __index__() to return a subclass of int. So, for the int constructor, I would have the following logic (assume appropriate try/catch): def __new__(cls, obj): i = obj.__int__() if type(i) is int: return i return i._internal_value Tim Delaney ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Thu, Apr 4, 2013 at 1:50 PM, Tim Delaney tim.dela...@aptare.com wrote: I fall into: 1. int(), float(), str() etc should return that exact class (and operator.index() should return exactly an int). 2. It could sometimes be useful for __int__() and __index__() to return a subclass of int. So, for the int constructor, I would have the following logic (assume appropriate try/catch): def __new__(cls, obj): i = obj.__int__() if type(i) is int: return i return i._internal_value CPython can solve this in C using an unsafe cast, and the code that checks for allowable subclasses of int actually ensures such a cast will work. But it still feels wrong; __int__ should be expected to do the work. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 5 Apr 2013 01:07, Chris Angelico ros...@gmail.com wrote: On Fri, Apr 5, 2013 at 1:59 AM, Guido van Rossum gu...@python.org wrote: On Thu, Apr 4, 2013 at 7:47 AM, Chris Angelico ros...@gmail.com wrote: Is there any argument that I can pass to Foo() to get back a Bar()? Would anyone expect there to be one? Sure, I could override __new__ to do stupid things, but in terms of logical expectations, I'd expect that Foo(x) will return a Foo object, not a Bar object. Why should int be any different? What have I missed here? A class can define a __new__ method that returns a different object. E.g. (python 3): Right, I'm aware it's possible. But who would expect it of a class? Python 3.3 does it for OSError to map errno values to the appropriate subclasses. That's mainly to aid migration to the new exception structure, though (see PEP 3151). For a clean slate API design you would use a separate factory function or class method to do the conversion. Cheers, Nick. ChrisA ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 05/04/13 01:23, Oscar Benjamin wrote: The reason for calling int(obj) is to get an object that is precisely of type int. When I call this I do not want any modified or additional methods or data attached to the resulting object. When I call int(), I'm expecting an int. That includes well-behaved subclasses of int that continue to behave like ints in all the ways that matter. It's curious to see the (d)evolution of thinking on type checking in Python circles. Once upon a time, type checking was discouraged, duck-typing was encouraged, and the philosophy was that an int is anything that behaves like an int. Now type-checking is tolerated or even encouraged, provided that you use isinstance, and an int is anything that inherits from the builtin (or the ABC). And this proposed change in behaviour continues the move away from Python's former emphasis on duck-typing. Now an int is only the builtin. Oscar, a question: what harm does it do to you if the int you receive has additional methods or data attached? I can appreciate Guido's concern that (say) a subclass might mess with the repr of the number, and he doesn't want that. (I don't find that argument compelling, but it does make sense.) But I don't understand why you would care if the int you receive happens to have an additional method or data that you don't expect. [...] I think it's fair to say that there are times when someone wants an object that is precisely of type int. They should be able to rely on int(obj) returning an int or raising an error. The first part of that is correct, but I disagree on the second. The 90-10 rule applies here. 90% of the time, we shouldn't care whether we receive an actual builtin int, only that we receive something that quacks like an int. In practice, that generally means something that inherits from int. IMO, int() and __int__ should support the common case, and not enforce the uncommon case This is true similarly for __index__. I have no argument with the idea that __index__ should guarantee to return a builtin int. I thought it already did make that guarantee. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/03/2013 09:04 AM, Steven D'Aprano wrote: On 04/04/13 01:16, Barry Warsaw wrote: It's analogous to all the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. Principle Of Least Surprise. My observation of the thread is that the majority of people feel of course __int__ needs to return a real int. People are surprised that you can return subclasses. Nick thought there was an explicit check to prevent it! Why is this so surprising? I think it's because int, str, and float are all classes. Therefore, as callables they are constructors. When you call a constructor, you expect to get an instance of that specific class. Yes, it's always been possible with new-style classes to return a subclass from the constructor. But calling a constructor and getting a subclass is always surprising behavior. Also, permitting subclasses means the interface becomes conceptually far more complicated. We would need to restrict it to subclasses that don't hijack the representation. It's plausible, for example, to write a subclass of str that uses a novel approach for storing the string data, say as a rope. It could overload all the magic methods and behave identically to a str in every important way. But if its __str__ returned self instead of a real str object, that means that PyUnicode_AS_UNICODE would blissfully return the bypassed internal string value, whatever it is, and Python breaks. So we can't enforce it programmatically, we'd need to document it as convention. But explaining that is complicated, and If The Implementation Is Hard To Explain, It's A Bad Idea. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? I'm much more interested in your counter use-case. When is it appealing or necessary to you to return a subclass of int from __int__()? In your postings so far you've said that this makes sense to you, but you haven't said why you need it. In lieu of a compelling use case, my vote is firmly against surprise and complexity. //arry/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 2 Apr 2013 19:04, Antoine Pitrou solip...@pitrou.net wrote: Le Tue, 2 Apr 2013 09:53:41 +0100, Mark Dickinson dicki...@gmail.com a écrit : On Tue, Apr 2, 2013 at 9:33 AM, Mark Shannon m...@hotpy.org wrote: Hence my original question: what *should* the semantics be? I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. Agreed. Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? (I like the idea of an explicit error over implicit conversion to the base type, so deprecation of subtypes makes sense as a way forward. We should check the other type coercion methods, too.) Cheers, Nick. Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Wed, Apr 3, 2013 at 12:17 PM, Nick Coghlan ncogh...@gmail.com wrote: Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? +1. Sounds good to me. (I like the idea of an explicit error over implicit conversion to the base type, so deprecation of subtypes makes sense as a way forward. We should check the other type coercion methods, too.) Agreed on both points. Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/03/2013 01:17 PM, Nick Coghlan wrote: I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. Agreed. Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? Why would one want to be absolutely sure of getting an int? It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. I can imagine numpy and similar projects would be making use of this ability already -- just think of uses for numpy's subclasses of float. If one wants to break the abstraction and be absolutely positively sure of getting an int and not a subclass thereof, they can write something like (0).__add__(obj). But I suspect this will be extremely rare. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 2013-04-03 13:47, Hrvoje Niksic wrote: On 04/03/2013 01:17 PM, Nick Coghlan wrote: I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. Agreed. Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? Why would one want to be absolutely sure of getting an int? It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. I can imagine numpy and similar projects would be making use of this ability already -- just think of uses for numpy's subclasses of float. We don't. [~] |1 type(float(np.float64(1.0))) float [~] |2 type(int(np.int32(1))) int -- Robert Kern I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth. -- Umberto Eco ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Apr 03, 2013, at 09:17 PM, Nick Coghlan wrote: Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? I definitely agree with doing this for __int__(), since it's intimately tied to int(), which is clearly a type conversion operation. It's analogous to all the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. __index__() is a bit trickier because it is not tied directly to type conversion. In this case, int subclasses could be valid, and as Hrvoje later points out, returning int-subclasses from __index__() should still work for all valid use cases. (Bug 17576 would still be a bug in this scenario, since obj.__index__() still needs to be called by operator.index() even when it's an int subclass.) (I like the idea of an explicit error over implicit conversion to the base type, so deprecation of subtypes makes sense as a way forward. We should check the other type coercion methods, too.) +1 -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 4 Apr 2013 00:18, Barry Warsaw ba...@python.org wrote: On Apr 03, 2013, at 09:17 PM, Nick Coghlan wrote: Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? I definitely agree with doing this for __int__(), since it's intimately tied to int(), which is clearly a type conversion operation. It's analogous to all the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. __index__() is a bit trickier because it is not tied directly to type conversion. In this case, int subclasses could be valid, and as Hrvoje later points out, returning int-subclasses from __index__() should still work for all valid use cases. Implementing __index__ just means This type can be converted to a Python integer without losing information. Aside from that extra without information loss qualification, it's the same as __int__. Cheers, Nick. (Bug 17576 would still be a bug in this scenario, since obj.__index__() still needs to be called by operator.index() even when it's an int subclass.) (I like the idea of an explicit error over implicit conversion to the base type, so deprecation of subtypes makes sense as a way forward. We should check the other type coercion methods, too.) +1 -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/03/2013 08:14 AM, Nick Coghlan wrote: On 4 Apr 2013 00:18, Barry Warsaw ba...@python.org mailto:ba...@python.org wrote: __index__() is a bit trickier because it is not tied directly to type conversion. In this case, int subclasses could be valid, and as Hrvoje later points out, returning int-subclasses from __index__() should still work for all valid use cases. Implementing __index__ just means This type can be converted to a Python integer without losing information. Aside from that extra without information loss qualification, it's the same as __int__. How is that possible? Whether int or int subclass, if I'm implementing __index__ it means my type is not an int subclass, and when I return an int I most certainly have lost information from the original type. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
Le Wed, 03 Apr 2013 08:21:22 -0700, Ethan Furman et...@stoneleaf.us a écrit : On 04/03/2013 08:14 AM, Nick Coghlan wrote: On 4 Apr 2013 00:18, Barry Warsaw ba...@python.org mailto:ba...@python.org wrote: __index__() is a bit trickier because it is not tied directly to type conversion. In this case, int subclasses could be valid, and as Hrvoje later points out, returning int-subclasses from __index__() should still work for all valid use cases. Implementing __index__ just means This type can be converted to a Python integer without losing information. Aside from that extra without information loss qualification, it's the same as __int__. How is that possible? Whether int or int subclass, if I'm implementing __index__ it means my type is not an int subclass, and when I return an int I most certainly have lost information from the original type. Without losing information about the numeric value. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 03/04/13 23:47, Hrvoje Niksic wrote: On 04/03/2013 01:17 PM, Nick Coghlan wrote: I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. Agreed. Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? Why would one want to be absolutely sure of getting an int? It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. I agree with Hrvoje here, and I have code that's probably going to be impacted by any change in behaviour. In OO terms, an instance of an int subclass *is* an int, and we shouldn't care whether __int__ returns a subclass or a builtin. I think that before any change is made, even mere DeprecationWarning, there needs to be a very strong reason justifying restricting __int__ to return a built-in int. To put it another way, I think it is perfectly reasonable for __int__ to enforce the constraint ``isinstance(result, int)`` but *not* to enforce the constraint ``type(result) is int``. We rarely, if ever, write explicit type checks like the second. Why should __int__ etc. implicitly do so? This issue doesn't just apply to ints. For example: py class MyStr(str): ... def __str__(self): ... return self ... py s = MyStr('spam') py type(str(s)) class '__main__.MyStr' This seems perfectly reasonable to me: __str__ is expected to return a string, and it does. If I absolutely must have a built-in str, I can do this: py type(''.join(s)) class 'str' But I can't really think of any cases where I am going to insist on a built-in str, instead of accepting anything that passes either the weaker isinstance check. Even if there are such cases, surely they are going to be rare and unusual. (I note that in OO terms, we don't really have good terminology for an instance of a class, excluding instances of any subclasses. That's because in OO terms we shouldn't care whether the type of the instance is the superclass or subclass, at least not in general.) -1 on forcing __int__, __str__, __float__ etc. to return instances of the built-in types. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/04/13 01:16, Barry Warsaw wrote: On Apr 03, 2013, at 09:17 PM, Nick Coghlan wrote: Perhaps we should start emitting a DeprecationWarning for int subclasses returned from __int__ and __index__ in 3.4? I definitely agree with doing this for __int__(), since it's intimately tied to int(), which is clearly a type conversion operation. It's analogous to all the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? As I see it, what I expect is this: n = int(something) assert isinstance(n, int) not this: n = int(something) assert type(n) is int I haven't cared about checking type identity since Unifying types and classes way back in Python 2.2, and I don't see why we should enforce a more restrictive rule now. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 04/03/2013 11:49 AM, Steven D'Aprano wrote: -1 on forcing __int__, __str__, __float__ etc. to return instances of the built-in types. - -1 as well, for the reasons Steven lists. The only quasi-legitimate reason I know of for checking 'type(x) is int' rather than 'isinstance(x, int)' is speed. Tres. - -- === Tres Seaver +1 540-429-0999 tsea...@palladion.com Palladion Software Excellence by Designhttp://palladion.com -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with undefined - http://www.enigmail.net/ iEYEARECAAYFAlFcV/wACgkQ+gerLs4ltQ6OBwCg0YMyUdiji82TwYQZTx85F9cJ wmMAoKBL13C+a4MN640jL5X+X+G9RP5b =8q3C -END PGP SIGNATURE- ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
I always intended for int() and str() to case subclasses to the built-in base class, and I don't want to change that rule. Consider a subclass of int() that overrides __repr__() and __str__() to print something fancy (maybe it defaults to hex; maybe it's an enum :-). I want to be able to say repr(int(x)) and get the standard decimal representation. Same with strings. If int() or str() were allowed to return a subclass instance, this wouldn't work, and I'd have to resort to draconian measures. (Betcha the first few solutions you come up with don't even work. :-) There are plenty of other use cases where a trivial subclass of one of the built-in types is used as some kind of flag -- e.g. maybe for values that ought to be serialized differently, or to enable some kind of type checking -- but it should always be possible to convert such values to the underlying base class to remove the special treatment. -- --Guido van Rossum (python.org/~guido ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/04/13 03:36, Guido van Rossum wrote: Consider a subclass of int() that overrides __repr__() and __str__() to print something fancy (maybe it defaults to hex; maybe it's an enum :-). I want to be able to say repr(int(x)) and get the standard decimal representation. Same with strings. If int() or str() were allowed to return a subclass instance, this wouldn't work, and I'd have to resort to draconian measures. int and str currently are allowed to return subclass instances. (Betcha the first few solutions you come up with don't even work. :-) Well, I'm always game to learn something. Challenge accepted. # Force a string subclass s to a built-in string. ''.join(s) # Force an int subclass n to a built-in int. (0).__add__(n) # And similarly for float subclass. 0.0.__add__(x) -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Apr 04, 2013, at 01:14 AM, Nick Coghlan wrote: Implementing __index__ just means This type can be converted to a Python integer without losing information. Aside from that extra without information loss qualification, it's the same as __int__. Hmm. object.__index__(self) Called to implement operator.index(). Also called whenever Python needs an integer object (such as in slicing, or in the built-in bin(), hex() and oct() functions). Must return an integer. operator.index(a) operator.__index__(a) Return a converted to an integer. Equivalent to a.__index__(). bin(x) Convert an integer number to a binary string. The result is a valid Python expression. If x is not a Python int object, it has to define an __index__() method that returns an integer. Certainly, in slicing an int subclass will work fine: class myint(int): ...pass ... range(10)[myint(2):myint(3)] range(2, 3) Same goes for hex/oct/bin: hex(myint(4)) '0x4' bin(myint(4)) '0b100' oct(myint(4)) '0o4' Also, hex/oct/bin aren't types, they're functions, so this doesn't seem equivalent to int or str for me. The latter two are much more equivalent to the built-in tuple, dict, and list types. So I don't think there's any inconsistency in allowing int subclasses to be returned from __index__(), and nothing should break, so I see no reason to change the status quo here. class anint(int): ... def __index__(self): ... return myint(self) ... from operator import index type(index(anint(7))) class '__main__.anint' Aside: It seems a bit odd to me that bin/hex/oct are defined to use __index__() instead of __int__(), but that's probably not worth arguing about. Cheers, -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Apr 04, 2013, at 03:04 AM, Steven D'Aprano wrote: On 04/04/13 01:16, Barry Warsaw wrote: the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? It's a consistency-of-implementation issue. Where built-in types are callable, they return concrete instances of themselves. This is true for e.g. list, tuple, dict, bytes, str, and should also be true of int. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Apr 03, 2013, at 01:46 PM, Barry Warsaw wrote: It's a consistency-of-implementation issue. Where built-in types are callable, they return concrete instances of themselves. This is true for e.g. list, tuple, dict, bytes, str, and should also be true of int. Well, I guess it's consistent for some of those built-in types wink. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/03/2013 10:46 AM, Barry Warsaw wrote: On Apr 04, 2013, at 03:04 AM, Steven D'Aprano wrote: On 04/04/13 01:16, Barry Warsaw wrote: the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? It's a consistency-of-implementation issue. Where built-in types are callable, they return concrete instances of themselves. This is true for e.g. list, tuple, dict, bytes, str, and should also be true of int. +1 ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 04/03/2013 01:50 PM, Ethan Furman wrote: On 04/03/2013 10:46 AM, Barry Warsaw wrote: On Apr 04, 2013, at 03:04 AM, Steven D'Aprano wrote: On 04/04/13 01:16, Barry Warsaw wrote: the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? It's a consistency-of-implementation issue. Where built-in types are callable, they return concrete instances of themselves. This is true for e.g. list, tuple, dict, bytes, str, and should also be true of int. Given that requirement, we still don't have to mandate that __int__ return an actual instance of the int type: the coercion could happen inside int() (as it would for any non-subclass). Tres. - -- === Tres Seaver +1 540-429-0999 tsea...@palladion.com Palladion Software Excellence by Designhttp://palladion.com -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with undefined - http://www.enigmail.net/ iEYEARECAAYFAlFcgVcACgkQ+gerLs4ltQ4ScwCfScssK/Cv74lPitQxbygmk5h/ RGoAnj2yUEgmEgorJi8GZh0GEB/iJrN1 =0I+y -END PGP SIGNATURE- ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/03/2013 12:21 PM, Tres Seaver wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 04/03/2013 01:50 PM, Ethan Furman wrote: On 04/03/2013 10:46 AM, Barry Warsaw wrote: On Apr 04, 2013, at 03:04 AM, Steven D'Aprano wrote: On 04/04/13 01:16, Barry Warsaw wrote: the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? It's a consistency-of-implementation issue. Where built-in types are callable, they return concrete instances of themselves. This is true for e.g. list, tuple, dict, bytes, str, and should also be true of int. Given that requirement, we still don't have to mandate that __int__ return an actual instance of the int type: the coercion could happen inside int() (as it would for any non-subclass). I don't understand. A non-int could only become an int via __int__, which int() calls. What magic is there in int() to turn any arbitrary object into an integer? -- class NonInt(): ... def __str__(self): ... return Not an integer! ... -- ni = NonInt() -- ni __main__.NonInt object at 0x267a090 -- str(ni) 'Not an integer!' -- int(ni) Traceback (most recent call last): File stdin, line 1, in module TypeError: int() argument must be a string or a number, not 'NonInt' -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 03/31/2013 09:13 PM, francis wrote: why is printing new class '__main__.Int2'? read twice before you write :-) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 2013-04-03, at 19:46 , Barry Warsaw wrote: On Apr 04, 2013, at 03:04 AM, Steven D'Aprano wrote: On 04/04/13 01:16, Barry Warsaw wrote: the other built-in types-as-functions, so int() calls __int__() which must return a concrete integer. Why must it? I think that's the claim which must be justified, not just taken as a given. When we call n = int(something), what's the use-case for caring that n is an instance of built-in int but not of a subclass, and is that use-case so compelling that it must be enforced for all uses of int() etc.? It's a consistency-of-implementation issue. Where built-in types are callable, they return concrete instances of themselves. This is true for e.g. list, tuple, dict, bytes, str, and should also be true of int. FWIW unless I missed something it's true for none of bytes, str or float, though it's true for complex (for some reason): types = (int, float, complex, bytes, str) Obj = type('Obj', (), { '__{0.__name__}__'.format(t): (lambda t: lambda self: type('my_{0.__name__}'.format(t), (t,), {})())(t) for t in types }) obj = Obj() for t in types: print({} = {} ? {}.format(t, type(t(obj)), type(t(obj)) is t)) python3 test.py class 'int' = class '__main__.my_int' ? False class 'float' = class '__main__.my_float' ? False class 'complex' = class 'complex' ? True class 'bytes' = class '__main__.my_bytes' ? False class 'str' = class '__main__.my_str' ? False bool can not be subclassed so the question doesn't make sense for it Broadly speaking (complex doesn't fit it), if there's a dedicated dunder method in the data model, the only check on what it returns is that it's a subtype of the conversion type. list, tuple and dict use non-dedicated conversion methods (iteration or a fallback thereof) so they don't have this occasion and have no choice but to instantiate themselves ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 03Apr2013 14:47, Hrvoje Niksic hrvoje.nik...@avl.com wrote: | On 04/03/2013 01:17 PM, Nick Coghlan wrote: | Why would one want to be absolutely sure of getting an int? So that arithmetic can be relied upon? If a subclass can override the add methods etc it can look like an int, be a subclass instance of an int, and yet not act like an int in all ways. If I go int(x), I personally want a real int out the end of it. -- Cameron Simpson c...@zip.com.au Q: What's the difference between a psychotic and a neurotic? A: A psychotic doesn't believe that 2 + 2 = 4. A neurotic knows it's true, but it bothers him. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 4/3/2013 3:36 PM, Ethan Furman wrote: On 04/03/2013 12:21 PM, Tres Seaver wrote: Given that requirement, we still don't have to mandate that __int__ return an actual instance of the int type: the coercion could happen inside int() (as it would for any non-subclass). I don't understand. A non-int could only become an int via __int__, which int() calls. What magic is there in int() to turn any arbitrary object into an integer? From the 2.7 manual: object.__complex__(self) object.__int__(self) object.__long__(self) object.__float__(self) Called to implement the built-in functions complex(), int(), long(), and float(). Should return a value of the appropriate type. I have always understood 'value of the appropriate type' to mean just what Guido says he intended it to mean. Changing to 'instance of the class or subclass thereof' is a change. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 04/04/13 09:07, Cameron Simpson wrote: On 03Apr2013 14:47, Hrvoje Niksic hrvoje.nik...@avl.com wrote: | On 04/03/2013 01:17 PM, Nick Coghlan wrote: | Why would one want to be absolutely sure of getting an int? So that arithmetic can be relied upon? If a subclass can override the add methods etc it can look like an int, be a subclass instance of an int, and yet not act like an int in all ways. Python is generally a consenting adults language. If you don't trust the subclass to actually behave like an int in ways that matter, why are you using it? Ultimately, something may have monkey-patched builtins int without your knowledge, so even calling int() doesn't guarantee anything about the object you get back. Isn't it funny how we have differences in opinion on just when and how we're allowed to shoot ourselves in the foot? I personally hate the idea that global constants aren't constant, and can be rebound by anything, but others apparently don't care. You hate the idea that int() might return an instance of a subclass, and I think that's a feature, not a bug. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Wed, Apr 3, 2013 at 6:47 AM, Hrvoje Niksic hrvoje.nik...@avl.com wrote: It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. Unless you want to try to use the concrete C-API in CPython. In my experience the concrete API is not very subclass friendly. -eric ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 4 Apr 2013 14:58, Eric Snow ericsnowcurren...@gmail.com wrote: On Wed, Apr 3, 2013 at 6:47 AM, Hrvoje Niksic hrvoje.nik...@avl.com wrote: It seems like a good feature that an __int__ implementation can choose to return an int subclass with additional (and optional) information. After all, int subclass instances should be usable everywhere where ints are, including in C code. Unless you want to try to use the concrete C-API in CPython. In my experience the concrete API is not very subclass friendly. Using it with subclasses is an outright bug (except as part of a subclass implementation). Cheers, Nick. -eric ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Tue, Apr 2, 2013 at 1:44 AM, Nick Coghlan ncogh...@gmail.com wrote: int() and operator.index() are both type coercion calls to produce true Python integers - they will never return a subclass, and this is both deliberate and consistent with all the other builtin types that accept an instance of themselves as input to the constructor. That's good to hear. There's code in the slot wrappers so that if you return a non-int object from either __int__ or __index__, then the interpreter will complain about it, and if you return a subclass, it will be stripped back to just the base class. Can you point me to that code? All I could find was PyLong_Check calls (I was looking for PyLong_CheckExact). Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On 02/04/13 01:44, Nick Coghlan wrote: On Mon, Apr 1, 2013 at 12:28 AM, Mark Dickinson dicki...@gmail.com mailto:dicki...@gmail.com wrote: As written, int_check would do the wrong thing for bools, too: I definitely want int(True) to be 1, not True. For (2) and (4), it's not so clear. Are there use-cases for an __index__ return value that's not directly of type int? I can't think of any offhand. int() and operator.index() are both type coercion calls to produce true Python integers - they will never return a subclass, and this is both deliberate and consistent with all the other builtin types that accept an instance of themselves as input to the constructor. Passing a subclass instance to the base class constructor is the way you convert a subclass to an ordinary instance of the base class: Unfortunately, that is not true :( class Int(int): ... def __int__(self): ... return self ... type(int(Int())) class '__main__.Int' Hence my original question: what *should* the semantics be? for base in (str, bytes, bytearray, int, float, complex, dict, tuple, list, set, frozenset): ... class subclass(base): pass ... print('type(base(subclass()))' is, type(base(subclass( ... 'type(base(subclass()))' is class 'str' 'type(base(subclass()))' is class 'bytes' 'type(base(subclass()))' is class 'bytearray' 'type(base(subclass()))' is class 'int' 'type(base(subclass()))' is class 'float' 'type(base(subclass()))' is class 'complex' 'type(base(subclass()))' is class 'dict' 'type(base(subclass()))' is class 'tuple' 'type(base(subclass()))' is class 'list' 'type(base(subclass()))' is class 'set' 'type(base(subclass()))' is class 'frozenset' There's code in the slot wrappers so that if you return a non-int object from either __int__ or __index__, then the interpreter will complain about it, and if you return a subclass, it will be stripped back to just the base class. If the language and library reference aren't clear on this, it's a documentation issue. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com mailto:ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Tue, Apr 2, 2013 at 9:33 AM, Mark Shannon m...@hotpy.org wrote: Hence my original question: what *should* the semantics be? I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. The question is whether / how to fix the current behaviour, given that it doesn't conform to those ideal semantics. Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Tue, Apr 2, 2013 at 10:53 AM, Mark Dickinson dicki...@gmail.com wrote: On Tue, Apr 2, 2013 at 9:33 AM, Mark Shannon m...@hotpy.org wrote: Hence my original question: what *should* the semantics be? I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. The question is whether / how to fix the current behaviour, given that it doesn't conform to those ideal semantics. Mark My 2 cents here is that which one is called seems to be truly random. Try looking into what builtin functions call (for example list.pop calls __int__, who knew) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
Le Tue, 2 Apr 2013 09:53:41 +0100, Mark Dickinson dicki...@gmail.com a écrit : On Tue, Apr 2, 2013 at 9:33 AM, Mark Shannon m...@hotpy.org wrote: Hence my original question: what *should* the semantics be? I like Nick's answer to that: int *should* always return something of exact type int. Otherwise you're always left wondering whether you have to do int(int(x)), or perhaps even int(int(int(x))), to be absolutely sure of getting an int. Agreed. Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Tue, Apr 2, 2013 at 9:58 AM, Maciej Fijalkowski fij...@gmail.com wrote: My 2 cents here is that which one is called seems to be truly random. Try looking into what builtin functions call (for example list.pop calls __int__, who knew) That sounds like a clear bug to me. It should definitely be using __index__. Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Tue, Apr 2, 2013 at 10:02 AM, Mark Dickinson dicki...@gmail.com wrote: On Tue, Apr 2, 2013 at 9:58 AM, Maciej Fijalkowski fij...@gmail.comwrote: My 2 cents here is that which one is called seems to be truly random. Try looking into what builtin functions call (for example list.pop calls __int__, who knew) That sounds like a clear bug to me. It should definitely be using __index__. Ah, and I see it *is* using `__index__` in Python 3; just not in Python 2.7. It may be one of those Python 2 bugs that's not worth fixing because the fix would do more harm (in the form of breakage of existing code) than good. -- Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Mon, Apr 1, 2013 at 12:28 AM, Mark Dickinson dicki...@gmail.com wrote: As written, int_check would do the wrong thing for bools, too: I definitely want int(True) to be 1, not True. For (2) and (4), it's not so clear. Are there use-cases for an __index__ return value that's not directly of type int? I can't think of any offhand. int() and operator.index() are both type coercion calls to produce true Python integers - they will never return a subclass, and this is both deliberate and consistent with all the other builtin types that accept an instance of themselves as input to the constructor. Passing a subclass instance to the base class constructor is the way you convert a subclass to an ordinary instance of the base class: for base in (str, bytes, bytearray, int, float, complex, dict, tuple, list, set, frozenset): ... class subclass(base): pass ... print('type(base(subclass()))' is, type(base(subclass( ... 'type(base(subclass()))' is class 'str' 'type(base(subclass()))' is class 'bytes' 'type(base(subclass()))' is class 'bytearray' 'type(base(subclass()))' is class 'int' 'type(base(subclass()))' is class 'float' 'type(base(subclass()))' is class 'complex' 'type(base(subclass()))' is class 'dict' 'type(base(subclass()))' is class 'tuple' 'type(base(subclass()))' is class 'list' 'type(base(subclass()))' is class 'set' 'type(base(subclass()))' is class 'frozenset' There's code in the slot wrappers so that if you return a non-int object from either __int__ or __index__, then the interpreter will complain about it, and if you return a subclass, it will be stripped back to just the base class. If the language and library reference aren't clear on this, it's a documentation issue. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
On Sun, Mar 31, 2013 at 2:29 PM, Mark Shannon m...@hotpy.org wrote: class Int1(int): def __init__(self, val=0): print(new %s % self.__class__) class Int2(Int1): def __int__(self): return self and two instances i1 = Int1() i2 = Int2() we get the following behaviour: type(int(i1)) class 'int' I would have expected 'Int1' Wouldn't that remove the one obvious way to get an 'int' from an 'Int1'? 1. Should type(int(x)) be exactly int, or is any subclass OK? 2. Should type(index(x)) be exactly int, or is any subclass OK? 3. Should int(x) be defined as int_check(x.__int__())? 4. Should operator.index(x) be defined as index_check(x.__index__())? For (1), I'd say yes, it should be exactly an int, so my answer to (3) is no. As written, int_check would do the wrong thing for bools, too: I definitely want int(True) to be 1, not True. For (2) and (4), it's not so clear. Are there use-cases for an __index__ return value that's not directly of type int? I can't think of any offhand. Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Semantics of __int__(), __index__()
and two instances i1 = Int1() i2 = Int2() we get the following behaviour: type(int(i1)) class 'int' I would have expected 'Int1' type(float(i1)) type 'float' type(float(i2)) class 'float' isinstance(int(i1), int) True isinstance(int(i2), int) new class '__main__.Int2' True isinstance(float(i1), float) True isinstance(float(i2), float) True why is printing new class '__main__.Int2'? ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com