用Python导入模块 - 最佳实践

时间:2012-03-28 22:58:43

标签: python coding-style workflow python-import

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

Python中的最佳做法是什么。我看到了一些具体的变化,我认为

没有区别

import pandasfrom pandas import *from pandas import DataFrame

前两个之间有什么区别,我应该导入我需要的东西。 此外,对于制作小程序来处理数据和计算简单统计数据的人来说,最糟糕的后果是什么。

更新

我发现了excellent guide。它解释了一切。

6 个答案:

答案 0 :(得分:42)

import pandas在pandas命名空间下导入pandas模块,因此您需要使用pandas.foo调用pandas中的对象。

from pandas import *将pandas模块中的所有对象导入当前命名空间,因此您只需使用foo调用pandas中的对象。请记住,如果当前命名空间和pandas命名空间之间存在任何命名冲突,则可能会产生未预见的后果。

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

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

答案 1 :(得分:26)

每种形式的缺点

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

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

from module import * 让我没有机会在语法上看到, 例如,classAclassB来自同一个模块 彼此有很多事情要做。 它使得阅读代码 hard 。 (这个名称源自此类导入 可能来自早期导入的阴影名称是该问题的最小部分。)

<强> from module import classA, classB, functionC, constantD, functionE 用太多的名字超载我的短期记忆 我在心理上需要分配给module才能 连贯地理解代码。

import modulewithaverylongname as mwvln 有时不够充分 对的记忆。

合适的妥协

基于上述观察,我开发了以下内容 我自己的代码中的样式:

如果模块名称很短,则

import module 是首选样式 例如标准库中的大多数包。 如果我需要使用模块中的名称,它也是首选的样式 在我自己的模块中只有两三个地方; 清晰度胜过简洁("Readability counts")。

import longername as ln 几乎是每个人的首选风格 其他情况。 例如,我可能import django.contrib.auth.backends as dj_abe。 根据上述标准1的定义,将使用缩写 经常,因此很容易记住。

只有这两种风格完全是pythonic "Explicit is better than implicit."规则。

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

答案 2 :(得分:23)

一般来说,最好是进行显式导入。 如:

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()

答案 3 :(得分:14)

以下是PEP8 Style Guide.

的一些建议
  1. 进口通常应分开,例如:

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

    但是可以

    from subprocess import Popen, PIPE
    
  2. 导入总是放在文件的顶部,就在任何模块注释和文档字符串之后,以及模块全局变量和常量之前。

    • 导入应按以下顺序分组:
      1. 标准库导入
      2. 相关的第三方导入
      3. 本地应用程序/库特定导入
    • 您应该在每组导入之间加一个空行。
  3. 建议使用绝对导入
    它们更易读,并且通过提供更好的错误消息来简化调试,以防您搞乱导入系统。

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

    显式相对导入

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

    No:  from ..grand_parent_package import uncle_package
    
  5. 应避免使用通配符导入(from <module> import *,因为它们不清楚命名空间中存在哪些名称,这会让读者和许多自动化工具感到困惑。

  6. python speed performance tips.

    中有关lazy imports的一些建议
      

    导入语句开销

         

    import语句几乎可以在任何地方执行。将它们置于功能内以限制其可见性和/或减少初始启动时间通常是有用的。尽管Python的解释器经过优化,不能多次导入同一个模块,但在某些情况下,重复执行import语句会严重影响性能。

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

    >>> 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
    

答案 4 :(得分:9)

from A import B

基本上等于以下三个陈述

import A
B = A.B
del A

就是这样,就是这一切。

答案 5 :(得分:2)

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

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