Re: [Python-Dev] Semantics of __int__(), __index__()

2013-04-06 Thread Terry Jan Reedy

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__()

2013-04-06 Thread Mark Dickinson
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__()

2013-04-05 Thread Stefan Behnel
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__()

2013-04-04 Thread Hrvoje Niksic

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__()

2013-04-04 Thread Oscar Benjamin
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__()

2013-04-04 Thread 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?

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__()

2013-04-04 Thread Georg Brandl
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__()

2013-04-04 Thread Guido van Rossum
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__()

2013-04-04 Thread Xavier Morel
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__()

2013-04-04 Thread Chris Angelico
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__()

2013-04-04 Thread Xavier Morel

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__()

2013-04-04 Thread Guido van Rossum
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__()

2013-04-04 Thread Antoine Pitrou
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__()

2013-04-04 Thread Ethan Furman

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__()

2013-04-04 Thread Tim Delaney
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__()

2013-04-04 Thread Guido van Rossum
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__()

2013-04-04 Thread Nick Coghlan
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__()

2013-04-04 Thread Steven D'Aprano

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__()

2013-04-04 Thread Larry Hastings


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__()

2013-04-03 Thread Nick Coghlan
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__()

2013-04-03 Thread Mark Dickinson
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__()

2013-04-03 Thread Hrvoje Niksic

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__()

2013-04-03 Thread Robert Kern

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__()

2013-04-03 Thread Barry Warsaw
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__()

2013-04-03 Thread Nick Coghlan
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__()

2013-04-03 Thread Ethan Furman

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__()

2013-04-03 Thread Antoine Pitrou
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__()

2013-04-03 Thread Steven D'Aprano

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__()

2013-04-03 Thread Steven D'Aprano

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__()

2013-04-03 Thread Tres Seaver
-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__()

2013-04-03 Thread Guido van Rossum
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__()

2013-04-03 Thread Steven D'Aprano

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__()

2013-04-03 Thread Barry Warsaw
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__()

2013-04-03 Thread Barry Warsaw
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__()

2013-04-03 Thread Barry Warsaw
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__()

2013-04-03 Thread Ethan Furman

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__()

2013-04-03 Thread Tres Seaver
-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__()

2013-04-03 Thread Ethan Furman

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__()

2013-04-03 Thread francis

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__()

2013-04-03 Thread Xavier Morel

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__()

2013-04-03 Thread Cameron Simpson
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__()

2013-04-03 Thread Terry Jan Reedy

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__()

2013-04-03 Thread Steven D'Aprano

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__()

2013-04-03 Thread 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.

-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__()

2013-04-03 Thread Nick Coghlan
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__()

2013-04-02 Thread Mark Dickinson
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__()

2013-04-02 Thread Mark Shannon



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__()

2013-04-02 Thread Mark Dickinson
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__()

2013-04-02 Thread Maciej Fijalkowski
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__()

2013-04-02 Thread Antoine Pitrou
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__()

2013-04-02 Thread Mark Dickinson
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__()

2013-04-02 Thread Mark Dickinson
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__()

2013-04-01 Thread Nick Coghlan
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__()

2013-03-31 Thread Mark Dickinson
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__()

2013-03-31 Thread francis



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