Re: [Python-Dev] Documentation Error for __hash__

2008-08-30 Thread Ondrej Certik
 I strongly advise people interested in this topic to take a closer look
 at the functionality that was added to address issue 2235. The don't
 inherit __hash__ behaviour has been backported from 3.0 and broke a
 bunch of code, but the naive fix of reverting to the 2.5 behaviour
 proceeded to make the 2.6 version of collections.Hashable completely
 useless (since pretty much *everything* then claimed to be hashable,
 including all of the container types in the standard library).

 After thrashing out those problems, the 2.6 behaviour ended up being:
 - __hash__ is still inherited by default
 - you can block inheritance explicitly by setting __hash__ = None in
 the class definition or on the class object
 - for a class defined in C, you can block __hash__ inheritance by
 setting the tp_hash slot to PyObject_HashNotImplemented
 - using one of the above approaches will cause hash(obj) to raise a
 TypeError, as will calling the tp_hash slot directly
 - unlike defining your own __hash__ method, using one of the above
 techniques will also mean that isinstance(obj, collections.Hashable)
 will also return False
 - defining __eq__ and/or __cmp__ without defining __hash__ will lead to
 a Py3k Warning being raised on the class definition when run with the -3
 switch

 The Python 3.0 behaviour is similar to the above, except that the
 unconditional inheritance of __hash__ is gone. If you define __eq__ or
 __cmp__ without defining __hash__, __hash__ will NOT be inherited from
 the parent class - instead, it will be set to None.

 The documentation of all of this could definitely use a bit more work -
 that's why I reopened 2235 in response to Michael's post.

Couple months ago I was trying to figure out how __eq__, __cmp__,
__hash__ and similar methods are called in Python and in which order
and wrote a docs here:

http://docs.sympy.org/python-comparisons.html

Feel free to reuse any of it. I wrote it to myself, as I didn't find
the official docs very clear.

Ondrej
___
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] Documentation Error for __hash__

2008-08-30 Thread Jesse Noller



On Aug 30, 2008, at 2:41 PM, Ondrej Certik [EMAIL PROTECTED] wrote:

I strongly advise people interested in this topic to take a closer  
look

at the functionality that was added to address issue 2235. The don't
inherit __hash__ behaviour has been backported from 3.0 and broke a
bunch of code, but the naive fix of reverting to the 2.5 behaviour
proceeded to make the 2.6 version of collections.Hashable completely
useless (since pretty much *everything* then claimed to be hashable,
including all of the container types in the standard library).

After thrashing out those problems, the 2.6 behaviour ended up being:
- __hash__ is still inherited by default
- you can block inheritance explicitly by setting __hash__ = None  
in

the class definition or on the class object
- for a class defined in C, you can block __hash__ inheritance by
setting the tp_hash slot to PyObject_HashNotImplemented
- using one of the above approaches will cause hash(obj) to raise a
TypeError, as will calling the tp_hash slot directly
- unlike defining your own __hash__ method, using one of the above
techniques will also mean that isinstance(obj, collections.Hashable)
will also return False
- defining __eq__ and/or __cmp__ without defining __hash__ will  
lead to
a Py3k Warning being raised on the class definition when run with  
the -3

switch

The Python 3.0 behaviour is similar to the above, except that the
unconditional inheritance of __hash__ is gone. If you define __eq__  
or
__cmp__ without defining __hash__, __hash__ will NOT be inherited  
from

the parent class - instead, it will be set to None.

The documentation of all of this could definitely use a bit more  
work -

that's why I reopened 2235 in response to Michael's post.


Couple months ago I was trying to figure out how __eq__, __cmp__,
__hash__ and similar methods are called in Python and in which order
and wrote a docs here:

http://docs.sympy.org/python-comparisons.html

Feel free to reuse any of it. I wrote it to myself, as I didn't find
the official docs very clear.

Ondrej


Ondrej, a patch that improves the official docs would be welcome and  
still potentially make 2.6/3.0

___
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] Documentation Error for __hash__

2008-08-30 Thread Ondrej Certik
 Ondrej

 Ondrej, a patch that improves the official docs would be welcome and still
 potentially make 2.6/3.0

That'd be awesome. I need to finish my thesis in the next couple days,
so I'd welcome if anyone could just take it and put usefult things in.
I could get to do it the next week the earliest.

Ondrej
___
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] Documentation Error for __hash__

2008-08-30 Thread Georg Brandl
Ondrej Certik schrieb:
 Ondrej

 Ondrej, a patch that improves the official docs would be welcome and still
 potentially make 2.6/3.0
 
 That'd be awesome. I need to finish my thesis in the next couple days,
 so I'd welcome if anyone could just take it and put usefult things in.
 I could get to do it the next week the earliest.

Doc patches are always accepted, and I intend to update the online 2.6 and
3.0 docs continually even when the finals are released, so there is no
particular deadline you have to make.

Georg

-- 
Thus spake the Lord: Thou shalt indent with four spaces. No more, no less.
Four shall be the number of spaces thou shalt indent, and the number of thy
indenting shall be four. Eight shalt thou not indent, nor either indent thou
two, excepting that thou then proceed to four. Tabs are right out.

___
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] Documentation Error for __hash__

2008-08-30 Thread Ondrej Certik
Hi Georg!

On Sat, Aug 30, 2008 at 11:09 PM, Georg Brandl [EMAIL PROTECTED] wrote:
 Ondrej Certik schrieb:
 Ondrej

 Ondrej, a patch that improves the official docs would be welcome and still
 potentially make 2.6/3.0

 That'd be awesome. I need to finish my thesis in the next couple days,
 so I'd welcome if anyone could just take it and put usefult things in.
 I could get to do it the next week the earliest.

 Doc patches are always accepted, and I intend to update the online 2.6 and
 3.0 docs continually even when the finals are released, so there is no
 particular deadline you have to make.

This is awesome, I didn't know you take care of the official docs too.

I'll send the doc patches when I get to it, unless someone else does
it before me.

Ondrej
___
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] Documentation Error for __hash__

2008-08-29 Thread M.-A. Lemburg
On 2008-08-28 21:31, Michael Foord wrote:
 Hello all,
 
 The documentation for __hash__ seems to be outdated. I'm happy to submit
 a patch, so long as I am not misunderstanding something.
 
 http://docs.python.org/dev/reference/datamodel.html#object.__hash__
 
 The documentation states:
 
 If a class does not define a __cmp__() or __eq__() method it should not
 define a __hash__() operation either; if it defines __cmp__() or
 __eq__() but not __hash__(), its instances will not be usable as
 dictionary keys. If a class defines mutable objects and implements a
 __cmp__() or __eq__() method, it should not implement __hash__(), since
 the dictionary implementation requires that a key's hash value is
 immutable (if the object's hash value changes, it will be in the wrong
 hash bucket).
 
 
 This may have been true for old style classes, but as new style classes
 inherit a default __hash__ from object - mutable objects *will* be
 usable as dictionary keys (hashed on identity) *unless* they implement a
 __hash__ method that raises a type error.

Being hashable is a different from being usable as dictionary key.

Dictionaries perform the lookup based on the hash value, but will
then have to check for hash collisions based on an equal comparison.

If an object does not define an equal comparison, then it is not
usable as dictionary key.

 Shouldn't the advice be that classes that implement comparison methods
 should always implement __hash__ (wasn't this nearly enforced?),

It's probably a good idea to implement __hash__ for objects that
implement comparisons, but it won't always work and it is certainly
not needed, unless you intend to use them as dictionary keys.

 and that mutable objects should raise a TypeError in __hash__.

That's a good idea, even though it's not needed either ;-)

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Aug 29 2008)
 Python/Zope Consulting and Support ...http://www.egenix.com/
 mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
 mxODBC, mxDateTime, mxTextTools ...http://python.egenix.com/


 Try mxODBC.Zope.DA for Windows,Linux,Solaris,MacOSX for free ! 


   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
___
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] Documentation Error for __hash__

2008-08-29 Thread Matt Giuca
 Being hashable is a different from being usable as dictionary key.

 Dictionaries perform the lookup based on the hash value, but will
 then have to check for hash collisions based on an equal comparison.

 If an object does not define an equal comparison, then it is not
 usable as dictionary key.


But if an object defines *neither* __eq__ or __hash__, then by default it is
usable as a dictionary key (using the id() of the object for both default
equality and hashing, which is fine, and works for all user-defined types by
default).

An object defining __hash__ but not __eq__ is not problematic, since it
still uses id() default for equality. (It just has potentially bad
dictionary performance, if lots of things hash the same even though they
aren't equal). This it not a problem by definition because *it is officially
okay for two objects to hash the same, even if they aren't equal, though
undesirable*.

So all hashable objects are usable as dictionary keys, are they not? (As far
as I know it isn't possible to have an object that does not have an equality
comparison, unless you explicitly override __eq__ and have it raise a
TypeError for some reason).

It's probably a good idea to implement __hash__ for objects that
 implement comparisons, but it won't always work and it is certainly
 not needed, unless you intend to use them as dictionary keys.


But from what I know, it is a *bad* idea to implement __hash__ for any
mutable object with non-reference equality (where equality depends on the
mutable state), as an unbreakable rule. This is because if they are inserted
into a dictionary, then mutated, they may suddenly be in the wrong bucket.
This is why all the mutable types in Python with non-reference equality (eg.
list, set, dict) are explicitly not hashable, while the immutable types (eg.
tuple, frozenset, str) are hashable, and so are the mutable types with
reference equality (eg. functions, user-defined classes by default).



  and that mutable objects should raise a TypeError in __hash__.

 That's a good idea, even though it's not needed either ;-)


So I think my above axioms are a better (less restrictive, and still
correct) rule than this one. It's OK for a mutable object to define
__hash__, as long as its __eq__ doesn't depend upon its mutable state. For
example, you can insert a function object into a dictionary, and mutate its
closure, and it won't matter, because neither the hash nor the equality of
the object is changing. It's only types like list and dict, with deep
equality, where you run into this hash table problem.
___
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] Documentation Error for __hash__

2008-08-29 Thread Michael Foord

M.-A. Lemburg wrote:

On 2008-08-28 21:31, Michael Foord wrote:
  

Hello all,

The documentation for __hash__ seems to be outdated. I'm happy to submit
a patch, so long as I am not misunderstanding something.

http://docs.python.org/dev/reference/datamodel.html#object.__hash__

The documentation states:

If a class does not define a __cmp__() or __eq__() method it should not
define a __hash__() operation either; if it defines __cmp__() or
__eq__() but not __hash__(), its instances will not be usable as
dictionary keys. If a class defines mutable objects and implements a
__cmp__() or __eq__() method, it should not implement __hash__(), since
the dictionary implementation requires that a key's hash value is
immutable (if the object's hash value changes, it will be in the wrong
hash bucket).


This may have been true for old style classes, but as new style classes
inherit a default __hash__ from object - mutable objects *will* be
usable as dictionary keys (hashed on identity) *unless* they implement a
__hash__ method that raises a type error.



Being hashable is a different from being usable as dictionary key.

Dictionaries perform the lookup based on the hash value, but will
then have to check for hash collisions based on an equal comparison.

If an object does not define an equal comparison, then it is not
usable as dictionary key.

  

Shouldn't the advice be that classes that implement comparison methods
should always implement __hash__ (wasn't this nearly enforced?),



It's probably a good idea to implement __hash__ for objects that
implement comparisons, but it won't always work and it is certainly
not needed, unless you intend to use them as dictionary keys.

  



So you're suggesting that we document something like.

Classes that represent mutable values and define equality methods are 
free to define __hash__ so long as you don't mind them being used 
incorrectly if treated as dictionary keys...


Technically true, but not very helpful in my opinion... :-)

Michael


and that mutable objects should raise a TypeError in __hash__.



That's a good idea, even though it's not needed either ;-)

  



--
http://www.ironpythoninaction.com/
http://www.voidspace.org.uk/
http://www.trypython.org/
http://www.ironpython.info/
http://www.resolverhacks.net/
http://www.theotherdelia.co.uk/

___
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] Documentation Error for __hash__

2008-08-29 Thread M.-A. Lemburg
On 2008-08-29 13:03, Matt Giuca wrote:
 Being hashable is a different from being usable as dictionary key.

 Dictionaries perform the lookup based on the hash value, but will
 then have to check for hash collisions based on an equal comparison.

 If an object does not define an equal comparison, then it is not
 usable as dictionary key.

 
 But if an object defines *neither* __eq__ or __hash__, then by default it is
 usable as a dictionary key (using the id() of the object for both default
 equality and hashing, which is fine, and works for all user-defined types by
 default).
 
 An object defining __hash__ but not __eq__ is not problematic, since it
 still uses id() default for equality. (It just has potentially bad
 dictionary performance, if lots of things hash the same even though they
 aren't equal). This it not a problem by definition because *it is officially
 okay for two objects to hash the same, even if they aren't equal, though
 undesirable*.

Note that only instances have the default hash value id(obj). This
is not true in general. Most types don't implement the tp_hash
slot and thus are not hashable. Indeed, mutable types should not
implement that slot unless they know what they're doing :-)

 So all hashable objects are usable as dictionary keys, are they not? (As far
 as I know it isn't possible to have an object that does not have an equality
 comparison, unless you explicitly override __eq__ and have it raise a
 TypeError for some reason).

Sorry, I wasn't clear enough: with not defining an equal comparison
I meant that an equal comparison does not succeed, ie. raises an
exception or returns Py_NotImplemented (at the C level).

Due to the default of using the id(obj) as fallback for the equal
comparison, this has to be explicitly coded for. If this is not
the case (and that's probably the most common situation),
then you're right: hashable implies usable as dictionary key.

 It's probably a good idea to implement __hash__ for objects that
 implement comparisons, but it won't always work and it is certainly
 not needed, unless you intend to use them as dictionary keys.

 
 But from what I know, it is a *bad* idea to implement __hash__ for any
 mutable object with non-reference equality (where equality depends on the
 mutable state), as an unbreakable rule. This is because if they are inserted
 into a dictionary, then mutated, they may suddenly be in the wrong bucket.
 This is why all the mutable types in Python with non-reference equality (eg.
 list, set, dict) are explicitly not hashable, while the immutable types (eg.
 tuple, frozenset, str) are hashable, and so are the mutable types with
 reference equality (eg. functions, user-defined classes by default).

Right.

By implementing __hash__ in classes you have the explicit choice of
either raising an exception or returning a useful hash value.

Again, the situation is better at the C level, since types
don't have a default tp_hash implementation, so have to explicitly
code such a slot in order for hash(obj) to work.

 and that mutable objects should raise a TypeError in __hash__.
 That's a good idea, even though it's not needed either ;-)

 
 So I think my above axioms are a better (less restrictive, and still
 correct) rule than this one. It's OK for a mutable object to define
 __hash__, as long as its __eq__ doesn't depend upon its mutable state. For
 example, you can insert a function object into a dictionary, and mutate its
 closure, and it won't matter, because neither the hash nor the equality of
 the object is changing. It's only types like list and dict, with deep
 equality, where you run into this hash table problem.

I think the documentation needs to be changed to make the defaults
explicit.

The documentation should probably say:

If you implement __cmp__ or
__eq__ on a class, also implement a __hash__ method (and either
have it raise an exception or return a valid non-changing hash
value for the object).

If you implement __hash__ on classes, you should consider implementing
__eq__ and/or __cmp__ as well, in order to control how dictionaries use
your objects.

In general, it's probably best to always implement both methods
on classes, even if the application will just use one of them.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Aug 29 2008)
 Python/Zope Consulting and Support ...http://www.egenix.com/
 mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
 mxODBC, mxDateTime, mxTextTools ...http://python.egenix.com/


 Try mxODBC.Zope.DA for Windows,Linux,Solaris,MacOSX for free ! 


   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
___
Python-Dev mailing list

Re: [Python-Dev] Documentation Error for __hash__

2008-08-29 Thread Matt Giuca

 It's probably a good idea to implement __hash__ for objects that
 implement comparisons, but it won't always work and it is certainly
 not needed, unless you intend to use them as dictionary keys.





 So you're suggesting that we document something like.

 Classes that represent mutable values and define equality methods are free
 to define __hash__ so long as you don't mind them being used incorrectly if
 treated as dictionary keys...

 Technically true, but not very helpful in my opinion... :-)


No, I think he was suggesting we document that if a class overrides __eq__,
it's a good idea to also implement __hash__, so it can be used as a
dictionary key.

However I have issues with this. First, he said:

It's probably a good idea to implement __hash__ for objects that
implement comparisons, but it won't always work and it is certainly
not needed, unless you intend to use them as dictionary keys.

You can't say certainly not needed unless you intend to use them as
dictionary keys, since if you are defining an object, you never know when
someone else will want to use them as a dict key (or in a set, mind!) So *if
possible*, it is a good idea to implement __hash__ if you are implementing
__eq__.

But also, it needs to be very clear that if you *should not* implement
__hash__ on a mutable object -- and it already is. So basically the docs
should suggest that it is a good idea to implement __hash__ if you are
implementing __eq__ on an immutable object.

HOWEVER,

There are two contradictory pieces of information in the docs.

a) if it defines
__cmp__()http://docs.python.org/dev/reference/datamodel.html#object.__cmp__or
__eq__() http://docs.python.org/dev/reference/datamodel.html#object.__eq__but
not
__hash__()http://docs.python.org/dev/reference/datamodel.html#object.__hash__,
its instances will not be usable as dictionary keys.
versus
b) User-defined classes have
__cmp__()http://docs.python.org/dev/3.0/reference/datamodel.html#object.__cmp__and
__hash__()http://docs.python.org/dev/3.0/reference/datamodel.html#object.__hash__methods
by default; with them, all objects compare unequal and
x.__hash__() returns id(x).

Note that these statements are somewhat contradictory: if a class has a
__hash__ method by default (as b suggests), then it isn't possible to not
have a __hash__ (as suggested by a).

In Python 2, statement (a) is true for old-style classes only, while
statement (b) is true for new style classes only. This distinction needs to
be made. (For old-style classes, it isn't the case that it has a __hash__
method by default - rather that the hash() function knows how to deal with
objects without a __hash__ method, by calling id()).

In Python 3, statement (a) is true always, while statement (b) is not (in
fact just the same as old-style classes are in Python 2). So the Python 3
docs can get away with being simpler (without having to handle that weird
case).

I just saw Marc-Andre's new email come in; I'll look at that now.

Matt
___
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] Documentation Error for __hash__

2008-08-29 Thread Matt Giuca
 Note that only instances have the default hash value id(obj). This
 is not true in general. Most types don't implement the tp_hash
 slot and thus are not hashable. Indeed, mutable types should not
 implement that slot unless they know what they're doing :-)


By instances you mean instances of user-defined classes?
(I carefully avoid the term instance on its own, since I believe that was
phased out when they merged types and classes; it probably still exists in
the C API but shouldn't be mentioned in Python-facing documentation).

But anyway, yes, we should make that distinction.

Sorry, I wasn't clear enough: with not defining an equal comparison
 I meant that an equal comparison does not succeed, ie. raises an
 exception or returns Py_NotImplemented (at the C level).


Oh OK. I didn't even realise it was valid or usual to explicitly block
__eq__ like that.


 Again, the situation is better at the C level, since types
 don't have a default tp_hash implementation, so have to explicitly
 code such a slot in order for hash(obj) to work.


Yes but I gather that this data model document we are talking about is not
designed for C authors, but Python authors, so it should be written for the
point of view of people coding only in Python. (Only the Extending and
Embedding and the C API documents are for C authors).

The documentation should probably say:

 If you implement __cmp__ or
 __eq__ on a class, also implement a __hash__ method (and either
 have it raise an exception or return a valid non-changing hash
 value for the object).


I agree, except maybe not for the Python 3 docs. As long as the behaviour I
am observing is well-defined and not just a side-effect which could go away
-- that is, if you define __eq__/__cmp__ but not __hash__, in a user-defined
class, it raises a TypeError -- then I think it isn't necessary to recommend
implementing a __hash__ method and raising a TypeError. Better just to leave
as-is (if it defines
__cmp__()http://docs.python.org/dev/3.0/reference/datamodel.html#object.__cmp__or
__eq__()http://docs.python.org/dev/3.0/reference/datamodel.html#object.__eq__but
not
__hash__()http://docs.python.org/dev/3.0/reference/datamodel.html#object.__hash__,
its instances will not be usable as dictionary keys) and clarify the later
statement.



 If you implement __hash__ on classes, you should consider implementing
 __eq__ and/or __cmp__ as well, in order to control how dictionaries use
 your objects.


I don't think I agree with that. I'm not sure why you'd implement __hash__
without __eq__ and/or __cmp__, but it doesn't cause issues so we may as well
not address it.


 In general, it's probably best to always implement both methods
 on classes, even if the application will just use one of them.


Well it certainly is for new-style classes in the 2.x branch. I don't think
you should implement __hash__ in Python 3 if you just want a non-hashable
object (since this is the default behaviour anyway).

A lot of my opinion here, though, which doesn't count very much -- so I'm
just making suggestions.

Matt
___
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] Documentation Error for __hash__

2008-08-29 Thread Nick Coghlan
Matt Giuca wrote:
 
 
 It's probably a good idea to implement __hash__ for objects that
 implement comparisons, but it won't always work and it is certainly
 not needed, unless you intend to use them as dictionary keys.
 
  
 
 
 
 So you're suggesting that we document something like.
 
 Classes that represent mutable values and define equality methods
 are free to define __hash__ so long as you don't mind them being
 used incorrectly if treated as dictionary keys...
 
 Technically true, but not very helpful in my opinion... :-)
 
 
 No, I think he was suggesting we document that if a class overrides
 __eq__, it's a good idea to also implement __hash__, so it can be used
 as a dictionary key.

I strongly advise people interested in this topic to take a closer look
at the functionality that was added to address issue 2235. The don't
inherit __hash__ behaviour has been backported from 3.0 and broke a
bunch of code, but the naive fix of reverting to the 2.5 behaviour
proceeded to make the 2.6 version of collections.Hashable completely
useless (since pretty much *everything* then claimed to be hashable,
including all of the container types in the standard library).

After thrashing out those problems, the 2.6 behaviour ended up being:
- __hash__ is still inherited by default
- you can block inheritance explicitly by setting __hash__ = None in
the class definition or on the class object
- for a class defined in C, you can block __hash__ inheritance by
setting the tp_hash slot to PyObject_HashNotImplemented
- using one of the above approaches will cause hash(obj) to raise a
TypeError, as will calling the tp_hash slot directly
- unlike defining your own __hash__ method, using one of the above
techniques will also mean that isinstance(obj, collections.Hashable)
will also return False
- defining __eq__ and/or __cmp__ without defining __hash__ will lead to
a Py3k Warning being raised on the class definition when run with the -3
switch

The Python 3.0 behaviour is similar to the above, except that the
unconditional inheritance of __hash__ is gone. If you define __eq__ or
__cmp__ without defining __hash__, __hash__ will NOT be inherited from
the parent class - instead, it will be set to None.

The documentation of all of this could definitely use a bit more work -
that's why I reopened 2235 in response to Michael's post.

Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://www.boredomandlaziness.org
___
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] Documentation Error for __hash__

2008-08-28 Thread Jeff Hall
I'm not sure about the first but as for the __reversed__ we had a discussion
yesterday and it was indeed added in 2.4 (oddly, my 2.5 documentation has
this correct... )

--
Haikus are easy
Most make very little sense
Refrigerator
___
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] Documentation Error for __hash__

2008-08-28 Thread Nick Coghlan
Michael Foord wrote:
 This may have been true for old style classes, but as new style classes
 inherit a default __hash__ from object - mutable objects *will* be
 usable as dictionary keys (hashed on identity) *unless* they implement a
 __hash__ method that raises a type error.
 
 Shouldn't the advice be that classes that implement comparison methods
 should always implement __hash__ (wasn't this nearly enforced?), and
 that mutable objects should raise a TypeError in __hash__.

Hmm, I thought I fixed those docs when I did the
PyObject_HashNotImplemented patch... (you can set __hash__ = None rather
than raising a TypeError explicitly now so that collections.Hashable
correctly returns False - the slot machinery in typeobject.c will then
take of turning that into PyObject_HashNotImplemented at the C level).

However, looking at the relevant checkins, it appears I only updated the
C API docs and didn't correct the library or language references.

I reopened http://bugs.python.org/issue2235 - there are some other doc
fixes I need to do this weekend for RC1, so I can tackle this at the
same time.

Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://www.boredomandlaziness.org
___
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] Documentation Error for __hash__

2008-08-28 Thread Terry Reedy



Jeff Hall wrote:
I'm not sure about the first but as for the __reversed__ we had a 
discussion yesterday and it was indeed added in 2.4 (oddly, my 2.5 
documentation has this correct... )


2.4 doc:
reversed( seq)

Return a reverse iterator. seq must be an object which supports the 
sequence protocol (the __len__() method and the __getitem__() method 
with integer arguments starting at 0). New in version 2.4.


[no mention of __reversed__]

3.3.6 Additional methods for emulation of sequence types

[ditto]

However, I confirmed that __reversed__ is used by reverse()

class C:
def __reversed__(self): return 'abc'

c=C()
print(reversed(c))


abc

___
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] Documentation Error for __hash__

2008-08-28 Thread Matt Giuca
 This may have been true for old style classes, but as new style classes
 inherit a default __hash__ from object - mutable objects *will* be usable as
 dictionary keys (hashed on identity) *unless* they implement a __hash__
 method that raises a type error.


I always thought this was a bug in new-style classes (due to the fact that,
as you say, they inherit __hash__ from object whether it's wanted or not).
However, it seems to be fixed in Python 3.0. So this documentation is only
wrong for Python 2.x branch.

See:

Python 2.6b3+ (trunk:66055, Aug 29 2008, 07:50:39)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type help, copyright, credits or license for more information.
 class X(object):
... def __eq__(self, other):
... return True
...
 x = X()
 hash(x)
-1211564180

versus

Python 3.0b3+ (py3k:66055M, Aug 29 2008, 07:52:23)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type help, copyright, credits or license for more information.
 class X(object):
... def __eq__(self, other):
... return True
...
 x = X()
 hash(x)
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: unhashable type: 'X'

Matt
___
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