关于python中的import、from、循环引用等相关问题

摘要

  • 关于导包问题,很少有人去在意它,但是它一直都在哪,也许出现了,百度一下就解决了,但是始终不理解。
  • 知识不存在不求甚解,授人鱼不如渔。
  • 不要拿pycharm中是否有导包提示来考虑此类问题
  • 不讨论内置包及第三方包
  • 不讨论通过sys.path.insert()方法添加进去的包

先说 from xx import yy 和import xx的区别:

  • from:程序进行的修改不会影响到被导入的原模块,且不同程序之间不会互相影响
  • import:当出现多个程序导入该模块时,会共用一个模块,程序之间会互相影响,包括原模块。

相对路径导入和绝对路径导入:

  • 相对路径:以正在编辑的那个模块为标准去引用
  • 绝对路径:以启动文件为标准去引用

再说包和包里的__init__.py:

  • __init__和其所在的目录一回事,导入这个包了,就相当于加载并导入这个__init__文件了,所以当你from这个包的时候,除了可以import这个包中的模块,还可以import_init_.py文件中的所有的东西。
  • __init__和其所在目录是同一级别的,但是它又确实在这个目录里面,所以想在__init__中导入其所在目录里面的文件的话,需要使用from . import yy的方式。
  • 另外,当你使用import导入一个包的时候,只是导入了这个包中__init__文件中的内容,比如:
    • import urllib 是不可使用request的,需要import urllib.request,而且这个时候你在使用request的时候,需要用urllib.request.xxx()的方式,而不是request.xxx(),这是因为你导入的是urllib.request,而不是request,urllib.request是一个整体。
  • 还有,如果使用 from xx import yy 的话:xx是其启动文件所在目录同级别的别的模块,或者包;而且,当满足下面条件的时候你不可以使用from .xx import yy,必须使用from xx import yy :
    • 需要导入xx的模块和xx模块及启动模块在同一级目录中。

然后是循环引用:

  • 所谓循环引用,类似死锁:你需要我的时候,我也导入你,下面针对一个常见的应用场景(延迟导入 lazy import)来做处理说明。
    • 假设A模块导入B模块,B模块中会使用A模块中的一个变量,那么A模块导入B模块的这个语句一定要放在该变量的下方。
    • 这样在B模块导入A模块的这个变量的时候,A 模块已经将这个变量加载出来了,避免循环引用。
    • 而且该文件还不能作为启动文件(为什么不能作为启动文件?这个问题我暂时未能解释。)

最后是如何避免循环引用?

  • 根本性思想:将循环变为单向。
  • 方案推荐:
    • 在设计时具有前瞻性(推荐)
    • 尝试函数中导入,或者底部导入(lazy import)(较为推荐)
    • 尝试使用import导入(较为推荐)
    • 重新组织代码 (推荐)
    • 合并代码
    • 分离代码(设计为类似树状结构)
    • 第二三种方法不保证一定成功

补充:建议一些朋友科普一下pep8的导包规范。

发布了55 篇原创文章 · 获赞 3 · 访问量 2739

猜你喜欢

转载自blog.csdn.net/rusi__/article/details/102996322