在Python中导入模块 – 最佳实践

我是Python的新手,因为我想要扩展使用R学习的技能。在RI中往往会加载一堆库,有时会导致函数名称冲突。

Python中的最佳实践是什么? 我看到一些具体的变化,我没有看到之间的差异

from pandas import * import pandasfrom pandas import DataFrame

前两者之间有什么区别,我应该只是import我所需要的。 另外,对于那些让小程序来处理数据和计算简单统计数据的人来说,最糟糕的后果是什么?

UPDATE

我发现这个优秀的指南 。 它解释了一切。

import pandas在pandas命名空间下import pandas模块,因此您需要使用pandas.foo来调用pandas中的pandas.foo

from pandas import *将pandas模块中的所有对象from pandas import *到当前命名空间中,因此您只需使用foo就可以在pandas中调用对象。 请记住,如果您的当前命名空间和pandas命名空间之间存在任何命名冲突,这可能会导致无法预料的后果。

from pandas import DataFrame与上面相同,只是将DataFrame (而不是所有内容)导入到当前名称空间中。

在我看来,第一个通常是最好的实践,因为它使不同的模块很好地划分在你的代码中。

一般来说,最好是做明确的import。 如:

 import pandas frame = pandas.DataFrame() 

要么:

 from pandas import DataFrame frame = DataFrame() 

Python中的另一个选项是,如果名称相互冲突,则将x导入为y:

 from pandas import DataFrame as PDataFrame from bears import DataFrame as BDataFrame frame1 = PDataFrame() frame2 = BDataFrame() 

每种forms的缺点

在阅读其他人的代码(以及那些使用非常不同的导入样式的人)时,我注意到了每种样式的以下问题:

import modulewithaverylongname将使用长模块名称(例如concurrent.futuresdjango.contrib.auth.backends )进一步混乱代码,并降低这些地方的可读性。

from module import *我没有机会看到语法,例如, classAclassB来自同一个模块,并有很多相互做。 这使得阅读代码很难 。 (从这样的导入名称可能会影响名称从早期import是这个问题的最小部分。)

from module import classA, classB, functionC, constantD, functionE重载我的短期内存太多的名字,我脑子需要分配给module ,以便连贯理解代码。

import modulewithaverylongname as mwvln有时对我来说是不够的助记符。

一个合适的妥协

基于上述观察,我在自己的代码中开发了以下风格:

如果模块名称很短,例如标准库中的大部分包,则import module是首选样式。 如果我需要在我自己的模块中的两三个地方使用模块中的名字,也是首选的样式; 清晰度胜过简洁( “可读性计数” )。

import longername as ln是几乎所有其他情况下的首选样式。 例如,我可能会import django.contrib.auth.backends as dj_abe 。 根据以上标准1的定义,缩写将被频繁使用,因此足够易于记忆。

只有这两种风格完全是pythonic根据“明确胜于暗示”。 规则。

from module import xx仍然有时在我的代码中出现。 我甚至as格式出现夸张的情况下使用它,最有名的例子是from datetime import datetime

 from A import B 

基本上等于三个陈述

 import A B = AB del A 

就是这样,就是这样。

以下是PEP8风格指南的一些build议。

  1. import通常应该分开 ,例如:

     Yes: import os import sys No: import sys, os 

    但是没关系

     from subprocess import Popen, PIPE 
  2. 导入总是放在文件的顶部,在任何模块注释和文档string之后,在模块全局variables和常量之前。

    • import应按以下顺序进行分组:
      1. 标准库导入
      2. 有关的第三方import
      3. 本地应用程序/库特定的导入
    • 您应该在每组导入之间留出一个空行。
  3. 推荐绝对import
    它们更具可读性,通过提供更好的错误消息来解决导入系统时的debugging问题。

     import mypkg.sibling from mypkg import sibling from mypkg.sibling import example 

    明确的相对import

     from . import sibling from .sibling import example 
  4. 隐式的相对导入不应该被使用,并在Python 3中被删除。

     No: from ..grand_parent_package import uncle_package 
  5. 应避免通配符导入( from <module> import * ,因为它们使名称空间中出现的名称不清楚,使读者和许多自动化工具混淆。


一些关于从python速度性能技巧中 lazy imports build议。

导入语句开销

导入语句可以在任何地方执行。 将它们放置在函数内以限制其可见性和/或减less初始启动时间通常是有用的。 虽然Python的解释器被优化为不能多次导入相同的模块,但在某些情况下,重复执行导入语句会严重影响性能。

下面给出的是在页面中解释的场景,

 >>> def doit1(): ... import string ... string.lower('Python') ... >>> import string >>> def doit2(): ... string.lower('Python') ... >>> import timeit >>> t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()') >>> t.timeit() 11.479144930839539 >>> t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()') >>> t.timeit() 4.6661689281463623 

它们都适用于不同的环境(这就是为什么它们都可用)。 没有深刻的指导原则,除了清晰,可维护和简单的通用母亲陈述。 我自己的代码中的一些例子:

  1. import sys, os, re, itertools避免了名称冲突,并提供了一个非常简洁的方式来导入一堆标准模块。
  2. from math import *让我写sin(x)而不是math.sin(x)在math重的代码。 当我导入numpy时,这会有点冒险,这会使其中的一些增加一倍,但它并不过分关注我,因为它们通常是相同的function。 另外,我倾向于遵循numpy文档 – import numpy as np – 这完全避开了这个问题。
  3. 我喜欢from PIL import Image, ImageDraw ,因为这就是PIL文档展示其示例的方式。