当前位置:  开发笔记 > 编程语言 > 正文

Python导入编码风格

如何解决《Python导入编码风格》经验,为你挑选了4个好方法。

我发现了一种新的模式.这种模式是众所周知的还是对它的看法是什么?

基本上,我很难刷新源文件以找出可用的模块导入等等,所以现在,而不是

import foo
from bar.baz import quux

def myFunction():
    foo.this.that(quux)

我将所有导入移动到它们实际使用的函数中,如下所示:

def myFunction():
    import foo
    from bar.baz import quux

    foo.this.that(quux)

这做了一些事情.首先,我很少意外地用其他模块的内容污染我的模块.我可以__all__为模块设置变量,但随后我必须在模块发展时更新它,这对于实际存在于模块中的代码无效.

其次,我很少在我的模块顶部进行一连串的进口,其中一半或更多我不再需要,因为我已经重构了它.最后,我发现这个模式更容易阅读,因为每个引用的名称都在函数体中.



1> aaronasterli..:

这个问题的(先前)最高投票答案格式很好,但性能绝对错误.让我来证明一下

性能

顶级导入

import random

def f():
    L = []
    for i in xrange(1000):
        L.append(random.random())


for i in xrange(1000):
    f()

$ time python import.py

real        0m0.721s
user        0m0.412s
sys         0m0.020s

在函数体中导入

def f():
    import random
    L = []
    for i in xrange(1000):
        L.append(random.random())

for i in xrange(1000):
    f()

$ time python import2.py

real        0m0.661s
user        0m0.404s
sys         0m0.008s

如您所见,在函数中导入模块可能有效.这样做的原因是简单的.它将引用从全局引用移动到本地引用.这意味着,至少对于CPython,编译器将发出LOAD_FAST指令而不是LOAD_GLOBAL指令.顾名思义,这些更快.另一个回答者sys.modules通过在循环的每个迭代中导入来人为地夸大了查看的性能.

通常,最好在顶部导入,但如果您多次访问模块,性能不是原因.原因是人们可以更容易地跟踪模块所依赖的内容,并且这样做与Python Universe的其余部分一致.


进口确实有一个非平凡的惩罚.这在本地访问以及函数中存在循环时会被混淆.如果在Top Import示例中添加"r = random"并使用r.random(),您将获得与第二个相同的性能.如果你添加"r = random.random"并使用"r()",它会更快.
+1用于引用实际的字节码差异...有时我会在方法中使用一些类属性,如果我要在函数中经常使用它们(更干净的字节码和更干净的代码)
哈,你现在是最高投票的答案,你可能想编辑以避免混淆....或者你是自我批评?
如果出于性能原因只想使用LOAD_FAST,请在全局级别上导入random,然后在本地范围内设置random_ = random,然后使用random_(或者更好的方法是,使用random_ = random.random保存一些属性查询) `或`from random import random`)。仅仅为了使用LOAD_FAST而在每个函数调用上都影响导入的性能是一个坏主意。

2> Ryan..:

这确实有一些缺点.

测试

如果您想通过运行时修改来测试模块,可能会使其变得更加困难.而不是做

import mymodule
mymodule.othermodule = module_stub

你必须这样做

import othermodule
othermodule.foo = foo_stub

这意味着您必须全局修补othermodule,而不是仅仅更改mymodule中的引用指向的内容.

依赖性跟踪

这使得模块所依赖的模块不明显.如果您使用许多第三方库或重新组织代码,这尤其令人恼火.

我不得不维护一些遗留代码,这些代码在整个地方使用了内联导入,这使得代码极难重构或重新打包.

关于表现的说明

由于python缓存模块的方式,没有性能损失.实际上,由于模块位于本地名称空间中,因此在函数中导入模块会有一些性能上的好处.

顶级导入

import random

def f():
    L = []
    for i in xrange(1000):
        L.append(random.random())

for i in xrange(10000):
    f()


$ time python test.py 

real   0m1.569s
user   0m1.560s
sys    0m0.010s

在函数体中导入

def f():
    import random
    L = []
    for i in xrange(1000):
        L.append(random.random())

for i in xrange(10000):
    f()

$ time python test2.py

real    0m1.385s
user    0m1.380s
sys     0m0.000s


您可能想澄清这一点 - 每次都会检查导入,但模块只加载一次.
这不是一个很好的例子,因为你将import _inside_放在for循环而不是f()的定义中.但是,是的,一般来说,本地进口确实有成本.
重新测试和更新.感谢您的反馈.

3> dF...:

这种方法存在一些问题:

打开文件所依赖的模块并不是很明显.

这将混淆要分析的依赖程序,如py2exe,py2app等.

您在许多功能中使用的模块怎么样?您最终会得到大量的冗余导入,或者您必须在文件的顶部和一些内部函数中放置一些.

所以...首选的方法是将所有导入放在文件的顶部.我发现如果我的导入很难跟踪,通常意味着我有太多的代码,我最好把它分成两个或更多的文件.

在那里我一些情况下已经发现里面进口的功能是有用的:

处理循环依赖(如果你真的无法避免它们)

平台特定代码

另外:在每个函数中放入导入实际上并不比文件顶部慢.第一次加载每个模块时,它被放入sys.modules,并且每个后续导入仅花费查找模块的时间,这相当快(不重新加载).



4> 小智..:

另一个有用的注意事项是from module import *在Python 3.0中删除了函数内部的语法.

这里简单提一下"删除的语法":

http://docs.python.org/3.0/whatsnew/3.0.html


他说进口的*部分*已被禁用.不要那么快速地投票给那些提供有用信息的人.
推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有