在Python中导入模块 – 最佳实践
我是Python的新手,因为我想要扩展使用R学习的技能。在RI中往往会加载一堆库,有时会导致函数名称冲突。
Python中的最佳实践是什么? 我看到一些具体的变化,我没有看到之间的差异
from pandas import *
import pandas
, from 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.futures
或django.contrib.auth.backends
)进一步混乱代码,并降低这些地方的可读性。
from module import *
我没有机会看到语法,例如, classA
和classB
来自同一个模块,并有很多相互做。 这使得阅读代码很难 。 (从这样的导入名称可能会影响名称从早期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议。
-
import通常应该分开 ,例如:
Yes: import os import sys No: import sys, os
但是没关系
from subprocess import Popen, PIPE
-
导入总是放在文件的顶部,在任何模块注释和文档string之后,在模块全局variables和常量之前。
- import应按以下顺序进行分组:
- 标准库导入
- 有关的第三方import
- 本地应用程序/库特定的导入
- 您应该在每组导入之间留出一个空行。
- import应按以下顺序进行分组:
-
推荐绝对import
它们更具可读性,通过提供更好的错误消息来解决导入系统时的debugging问题。import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
或明确的相对import
from . import sibling from .sibling import example
-
隐式的相对导入不应该被使用,并在Python 3中被删除。
No: from ..grand_parent_package import uncle_package
-
应避免通配符导入(
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
它们都适用于不同的环境(这就是为什么它们都可用)。 没有深刻的指导原则,除了清晰,可维护和简单的通用母亲陈述。 我自己的代码中的一些例子:
-
import sys, os, re, itertools
避免了名称冲突,并提供了一个非常简洁的方式来导入一堆标准模块。 -
from math import *
让我写sin(x)
而不是math.sin(x)
在math重的代码。 当我导入numpy时,这会有点冒险,这会使其中的一些增加一倍,但它并不过分关注我,因为它们通常是相同的function。 另外,我倾向于遵循numpy文档 –import numpy as np
– 这完全避开了这个问题。 - 我喜欢
from PIL import Image, ImageDraw
,因为这就是PIL文档展示其示例的方式。