propias procedimientos lista graficos graficas graficar funciones coordenadas python hash

procedimientos - ¿Por qué y cómo son halables las funciones de Python?



lista de funciones de python (3)

No es nada especial. Como puede ver si examina el método de __hash__ del tipo de función:

>>> def f(): pass ... >>> type(f).__hash__ <slot wrapper ''__hash__'' of ''object'' objects>

la parte of ''object'' objects significa que simplemente hereda el object __hash__ basado en identidad predeterminado. Función == y hash funcionan por identidad. La diferencia entre id y hash es normal para cualquier tipo que herede el object.__hash__ :

>>> x = object() >>> id(x) 40145072L >>> hash(x) 2509067

Podrías pensar que __hash__ solo se debe definir para objetos inmutables, y estarías casi en lo cierto, pero le falta un detalle clave. __hash__ solo se debe definir para objetos en los que todo lo que está involucrado en las comparaciones == es inmutable. Para los objetos cuyo == se basa en la identidad, también es completamente estándar basar el hash en la identidad, ya que incluso si los objetos son mutables, no es posible que se puedan modificar de manera que cambien su identidad. Los archivos, módulos y otros objetos mutables con identidad == todos se comportan de esta manera.

Recientemente probé los siguientes comandos en Python:

>>> {lambda x: 1: ''a''} {<function __main__.<lambda>>: ''a''} >>> def p(x): return 1 >>> {p: ''a''} {<function __main__.p>: ''a''}

El éxito de ambas creaciones dict indica que tanto las funciones regulares como las lambda son manejables. (Algo como {[]: ''a''} falla con TypeError: unhashable type: ''list'' ).

El hash aparentemente no es necesariamente el ID de la función:

>>> m = lambda x: 1 >>> id(m) 140643045241584 >>> hash(m) 8790190327599 >>> m.__hash__() 8790190327599

El último comando muestra que el método __hash__ está explícitamente definido para lambda s, es decir, esto no es algo automatico que Python computa basado en el tipo.

¿Cuál es la motivación detrás de hacer las funciones hashable? Para obtener una bonificación, ¿cuál es el hash de una función?


Puede ser útil, por ejemplo, para crear conjuntos de objetos de función, o para indexar un dict por funciones. Los objetos inmutables normalmente soportan __hash__ . En cualquier caso, no hay diferencia interna entre una función definida por una def o por una lambda , eso es puramente sintáctico.

El algoritmo utilizado depende de la versión de Python. Parece que estás usando una versión reciente de Python en una caja de 64 bits. En ese caso, el hash de un objeto de función es la rotación correcta de su id() en 4 bits, con el resultado visto como un entero de 64 bits con signo. El cambio a la derecha se realiza porque las direcciones de los objetos (resultados de id() están generalmente alineadas de modo que sus últimos 3 o 4 bits siempre son 0, y esa es una propiedad ligeramente molesta para una función de hash.

En tu ejemplo específico,

>>> i = 140643045241584 # your id() result >>> (i >> 4) | ((i << 60) & 0xffffffffffffffff) # rotate right 4 bits 8790190327599 # == your hash() result


Una función es hashable porque es un objeto normal, incorporado, no mutable.

Del manual de Python :

Un objeto es manejable si tiene un valor hash que nunca cambia durante su vida útil (necesita un __hash__() ), y se puede comparar con otros objetos (necesita un __eq__() o __cmp__() ). Los objetos que se pueden comparar y que son iguales deben tener el mismo valor hash.

La capacidad de acceso hace que un objeto se pueda utilizar como una clave de diccionario y un miembro del conjunto, porque estas estructuras de datos usan el valor de hash internamente.

Todos los objetos incorporados inmutables de Python son lavables, mientras que no hay contenedores mutables (como listas o diccionarios). Los objetos que son instancias de clases definidas por el usuario son manejables por defecto; todos comparan desigual (excepto con ellos mismos), y su valor hash se deriva de su id() .