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

在Python中导入模块-最佳实践,python,coding-style,workflow,python-import,Python,Coding Style,Workflow,Python Import,我是Python新手,因为我想扩展我使用R。 在R中,我倾向于加载一堆库,有时会导致函数名冲突 Python中的最佳实践是什么。我看到了一些具体的变化,我看不出它们之间有什么区别 导入熊猫,从熊猫导入*,以及从熊猫导入数据帧 前两者之间有什么区别?我应该只导入我需要的东西吗。 另外,对于那些制作小程序来处理数据和计算简单统计数据的人来说,最糟糕的后果是什么 更新 我找到了这个。它解释了一切。import pandas在pandas名称空间下导入pandas模块,因此您需要使用pandas.foo

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

Python中的最佳实践是什么。我看到了一些具体的变化,我看不出它们之间有什么区别

导入熊猫
从熊猫导入*
,以及
从熊猫导入数据帧

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

更新


我找到了这个。它解释了一切。

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

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

导入数据帧的
与上面相同,但只将
数据帧
(而不是所有内容)导入当前命名空间


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

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

或:

Python中的另一个选项是,当名称冲突时,将x作为y导入:

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

它们都适用于不同的环境(这就是它们都可用的原因)。除了关于清晰性、可维护性和简单性的通用母性声明之外,没有深入的指导原则。我自己代码中的一些示例:

  • 导入sys、os、re、itertools
    避免了名称冲突,并提供了一种非常简洁的方法来导入一组标准模块
  • from math import*
    允许我编写
    sin(x)
    而不是
    math.sin(x)
    数学重码。当我还导入numpy时,这有点冒险,它在其中一些函数上加倍,但我并不太担心,因为它们通常都是相同的函数。另外,我倾向于遵循numpy文档-
    将numpy导入为np
    ,这完全回避了这个问题
  • 我喜欢来自PIL导入图像的
    ,ImageDraw
    ,因为这是PIL文档展示其示例的方式
  • 本质上等于以下三个陈述

    import A
    B = A.B
    del A
    
    就这样,就这样。

    每种形式的缺点 当阅读别人的代码时(这些人使用 不同的导入样式),我注意到 每种样式:

    导入模块verylongname
    将使代码更加混乱 使用长模块名(例如,
    concurrent.futures
    django.contrib.auth.backends
    ),并降低这些位置的可读性

    从模块导入*
    中,我没有机会从语法上看到, 例如,
    classA
    classB
    来自同一模块和 彼此有很多关系。 这使得阅读代码变得困难。 (b)从该项进口 可能来自早期导入的阴影名称是该问题的最小部分。)

    从模块导入classA、classB、functionC、constantD、functionE
    名字太多,使我的短期记忆超载 我心里需要分配给
    模块
    ,以便 连贯地理解代码

    导入模块作为mwvln的长名称有时不够
    对我来说有助于记忆

    适当的妥协 基于以上观察,我得出以下结论 我自己的代码中的样式:

    如果模块名称较短,则首选导入模块 例如,标准库中的大多数包。 如果我需要使用中模块的名称,它也是首选样式 在我自己的模块中只有两三个位置; 那么,清晰胜过简洁()

    导入longername as ln
    几乎在所有应用程序中都是首选样式 其他情况。 例如,我可能
    将django.contrib.auth.backends导入为djcab
    。 根据上述标准1的定义,将使用缩写 经常,因此足够容易记忆

    根据 规则

    从模块导入xx
    有时仍会出现在我的代码中。 我使用它的情况下,即使是
    as
    格式出现夸张, 最著名的例子是来自datetime导入datetime的
    
    
    (但是如果我需要更多的元素,我将
    导入datetime作为dt
    )。

    以下是来自

  • 导入通常应在单独的行上,例如:

    Yes: import os
         import sys
    
    No:  import sys, os
    
    但是可以

    from subprocess import Popen, PIPE
    
  • 导入始终放在文件的顶部,紧跟在任何模块注释和docstring之后,模块全局变量和常量之前。

    • 导入应按以下顺序分组:
    • 标准库导入
    • 相关第三方进口
    • 本地应用程序/库特定导入
    • 您应该在每组导入之间放置一个空行
  • 建议绝对进口
    它们更具可读性,并且在导入系统出错时提供更好的错误消息,从而使调试更容易

    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example
    
    或显式相对导入

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

    No:  from ..grand_parent_package import uncle_package
    
  • 通配符导入(import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
  • from . import sibling
    from .sibling import example
    
    No:  from ..grand_parent_package import uncle_package
    
    >>> 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