¿Por qué scipy importa el trabajo espacial, mientras que scipy.spatial no funciona después de importar scipy?

Me gustaría usar scipy.spatial.distance.cosine en mi código. Puedo importar el submódulo spatial si hago algo como import scipy.spatial o from scipy import spatial , pero si simplemente import scipy scipy.spatial.distance.cosine(...) da como resultado el siguiente error: AttributeError: 'module' object has no attribute 'spatial' .

¿Qué hay de malo con el segundo enfoque?

Importar un paquete no importa el submódulo automáticamente. Necesitas importar submódulo explícitamente.

Por ejemplo, import xml no importa el submódulo xml.dom

 >>> import xml >>> xml.dom Traceback (most recent call last): File "", line 1, in  AttributeError: 'module' object has no attribute 'dom' >>> import xml.dom >>> xml.dom  

Hay una excepción como os.path . (El propio módulo OS importa el submódulo en su espacio de nombres)

 >>> import os >>> os.path  

Eso es porque scipy es un paquete , no un módulo. Cuando importa un paquete, en realidad no carga los módulos en el interior y, por lo tanto, package.module provoca un error.

Sin embargo, import package.module funcionaría, ya que carga el módulo, no el paquete.

Este es el comportamiento estándar para la mayoría de las declaraciones de importación, pero hay algunas excepciones.

Este es el mismo caso para urllib en Python 3:

 >>> import urllib >>> dir(urllib) ['__builtins__', '__cached__', '__doc__', '__file__', '__initializing__', '__loader__', '__name__', '__package__', '__path__', 'error', 'parse', 'request', 'response'] 

¿Ver? no hay submódulos allí. Para acceder a su submódulo, solicitamos el submódulo:

 >>> import urllib.request >>> 

Espero que esta sencilla explicación ayude!