繁体   English   中英

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

[英]Importing modules in Python - best practice

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

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

import pandasfrom pandas import *from pandas import DataFrame

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

更新

我找到了这个优秀的指南 它解释了一切。

每种形式的缺点

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

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

from module import *让我没有机会在语法上看到,例如, classAclassB来自同一个模块并且彼此有很多关系。 它使阅读代码变得困难 (来自此类导入的名称可能会影响来自较早导入的名称是该问题的至少一部分。)

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 djcab 根据上述标准 1 的定义,缩写将被频繁使用,因此很容易记住。

根据“显式优于隐式”,只有这两种样式是完全 Pythonic 的 规则。

from module import xx有时仍会出现在我的代码中。 我会在甚至as格式显得夸大的情况下使用它,最著名的例子是from datetime import datetime (但如果我需要更多元素,我会将import datetime as dt )。

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

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

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

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

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

import pandas
frame = pandas.DataFrame()

要么:

from pandas import DataFrame
frame = DataFrame()

当名称冲突时,Python 中的另一个选项是 import x as y:

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

以下是PEP8 风格指南中的一些建议

  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 * ,因为它们使命名空间中存在哪些名称变得不清楚,使读者和许多自动化工具都感到困惑。


关于从python 速度性能提示中lazy imports一些建议

导入语句开销

import 语句几乎可以在任何地方执行。 将它们放在函数中以限制它们的可见性和/或减少初始启动时间通常很有用。 尽管 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
from A import B

基本上等于以下三个语句

import A
B = A.B
del A

就是这样,就是这样。

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

  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 文档展示其示例的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM