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-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
>> 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 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
> 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-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-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__()or
__eq__()but
not
__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 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__()or
__eq__() but
not
__hash__(),
its instances will not be usable as dictionary keys."
versus
b) "User-defined classes have
__cmp__()and
__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 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
___

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 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 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-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 "", line 1, in 
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


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


[Python-Dev] Documentation Error for __hash__

2008-08-28 Thread Michael Foord

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.


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__.


Additionally the following documentation states that __reversed__ is new 
in Python 2.6 and I think it was actually new in Python 2.4 (it 
certainly works for Python 2.5 and IronPython 1 which targets 2.4...).


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

Michael Foord

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

___
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