Mon, 30 Sep 2002 22:16:37 +0900, William Djaja Tjokroaminata billtj@z.glue.umd.edu pisze:
Everything below is “obvious” and natural, isn’t it? That’s why
I don’t understand why Python does not allow mutable object to be
used as a hash/dictionary key in the first place.
It’s not obvious that a Ruby hash doesn’t put given objects as keys
but their duplicates. In Python it puts the keys as given (strings
and tuples are immutable so it would be a waste of time and memory
to make duplicates).
I think the difference between Python and Ruby is more philosophical
than technical, i.e. there mutable and immutable objects are
technically about the same.
Technically “immutable” means that there is no operation provided which
changes the state of the object. Philosophically it means that the
object’s identity is an artifact of the implementation and shouldn’t
be taken into account, only the value matters. It implies that passing
them by reference and by value is the same. All immutable objects of
some kind with the given value are equivalent. The implementation is
free to merge or disjoin representations of immutable objects when
it wants.
In Ruby any object can be frozen. In Python immutable and mutable
types are usually separate: mutability is not an attribute of an
object but a property of its type. (User-defined classes are not
formally classified, only intentionally.)
Python doesn’t enforce the consistency of treatment of these kinds
of objects: it allows to compare identity of immutable objects like
numbers (with unspecified results when objects are equal) and it
allows to use user-defined objects as keys of hashes, hoping that
their hash and equality relations won’t change over time.
Python tuples are different from lists (i.e. really arrays but
python calls them lists) also in this respects: tuples are usually
heterogeneous and of a fixed length, i.e. the length is usually
statically known in places they are used; lists are usually homogeneous
and of variable length.
Tuples are represented more efficiently than lists:
#define PyObject_HEAD
int ob_refcnt;
struct _typeobject *ob_type;
#define PyObject_VAR_HEAD
PyObject_HEAD
int ob_size; /* Number of items in variable part */
typedef struct {
PyObject_VAR_HEAD
PyObject *ob_item[1];
} PyTupleObject;
// Allocated with the additional space for elements.
typedef struct {
PyObject_VAR_HEAD
PyObject **ob_item;
} PyListObject;
// Capacity is implied by rounded size.
···
–
__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ Blog człowieka poczciwego.