原文发表在我的博客主页,转载请注明出处!


建议十八:有节制的使用from...import语句

python提供了三种方式引入外部模块:

  • import语句
  • from...import...
  • __import__函数

使用的时候需要注意以下几点:

  • 一般情况下尽量优先使用import a形式,如访问B时需要使用a.B的形式
  • 有节制地使用from a import B形式,可以直接访问B
  • 尽量避免使用from a import *,因为这会污染命名空间,并且无法清晰地表示导入了哪些对象

首先简单的了解下python的import机制。python在初始化运行环境的时候会预先加载一批内建模块到内存中,这些模块相关的信息被存放在sys.modules中,当加载一个模块的时候,解释器世嘉尚要完成以下动作:

  • 在sys.modules中进行搜索看看该模块是否已经存在,如果存在,则将其导入到当前局部命名空间,加载结束
  • 如果在sys.modules中找不到对应模块的名称,则为需要导入的模块创建一个字典对象,并将该对象信息插入sys.modules中
  • 加载前确认是否需要对模块对应的文件进行编译,如果需要则先进行编译
  • 执行动态加载,在当前模块的命名空间中执行编译后的字节码,并将其中所有的对象放入模块对应的字典中。

如果无节制的使用from a import ...会带来以下问题:

  • 命名空间冲突

    一般来说在非常明确不会造成明明冲突的前提下,以下几种情况下可以考虑使用from...import语句
  • 当只需要导入部分属性或方法时
  • 模块中的这些属性和方法访问频率较高导致使用“模块名.名称”的形式进行访问过于繁琐时
  • 模块的文档明确说明需要使用from..import形式,导入的是一个包下面的子模块,且能够更为简单和便利时
  • 循环嵌套导入的问题
c1.py:
from c2 import g
def x():
pass
c2.py:
from c1 import x
def g():
pass

有时间可以试试上面的导入,会抛出ImportError异常,但是直接使用import就可以。


建议十九:优先使用absolute import来导入模块

相对导入:在不指明package名的情况相爱导入自己这个package的模块

绝对导入:指明顶层package名,python会在sys.path中寻找所有的顶层模块

加入有如下文件结构,其中app/sub1/string.py中定义了一个lower()方法。

app/
__init__.py
sub1/
__init__.py
mod1.py
string.py
sub2/
__init__.py
mod2.py

经验告诉我们,挡在mod1.py中import string之后,调用string.lower()方法时,会覆盖掉python自带的string模块中的方法。所以如果要使用python的String模块中的方法呢?

python2.5后为absolute import提供了一种新的机制,在模块中使用from _future_ import absolute_import语句进行说明后再进行导入,会禁用implicit relative,但是并不会禁掉explicit relative import。同时类似于linux,它还通过点号提供了一种显式进行relative import的方法,“.”表示当前目录,“..”表示当前目录的上一层目录。

相比于absolute import,relative import的问题比较多,因此推荐优先使用absolute import。


建议二十:i+=1 不等于 ++i

python的解释器会将++i操作解释为+(+i),其中+号表示证书符号,--i也类似。


建议二十一:使用with自动关闭资源

with语句的语法为:

with exp1 [as target]:
code... #嵌套
with expr1 as e1:
with expr2 as e2
等价于
with expr1 as e1, expr2 as e2

with语句可以在代码块执行完毕后进入该代码块时的现场,执行过程如下:

  • 计算表达式的值,返回一个上下文管理器对象
  • 加载上下文管理器对象的__exit__()方法以备后用
  • 调用上下文管理器对象的__enter__()方法
  • 如果with语句中设置了目标对象,则将__enter__()方法的返回值复制给目标对象
  • 执行with中的代码块
  • 如果步骤5中代码正常结束,调用上下文管理器对象的__exit__()方法,其返回值忽略
  • 如果步骤5中代码执行过程中发生异常,调用上下文管理器对象的__exit__()方法,并将异常类型、值及traceback信息作为参数传递给__exit__()方法,如果__exit__()返回值为false,则异常值会被重新抛出;否则挂起异常,程序继续执行。

上下文管理器:用来创建一个运行时的环境,是一个对象,定义程序运行时需要建立的上下文,处理程序的进入和退出,实现了上下文管理协议,即在对象中定义了__enter__()和__exit__()方法:

  • enter():进入运行时的上下文,返回运行时上下文相关的对象
  • exit(exception_type, exception_value, traceback):退出运行时的上下文,定义在块执行(或终止)之后上下文管理器应该做什么。

建议二十二:使用else子句简化循环(异常处理)

在python中,不仅分支语句有else子句,循环语句和异常处理也有。

首先看循环语句中的else,语法为:

#while循环
"while" expre ":" suite
["else" ":" suite]
#for循环
"for" target_list "in" expre_list ":" suite
["else" ":" suite]

具体不再赘述,下面两端代码具有同样的功能,可以进行比较。

def print_prime(n):
for i in xrange(2, n):
found = True
for j in xrange(2, i):
if i % j == 0:
found = False
break
if found:
print i
def print_prime2(n):
for i in xrange(2, n):
for j in xrange(2, i):
if i % j == 0:
break
else:
print i

和循环语句中的else相似,异常处理也提供了else子句语法,直接看例子

def save(db, obj):
try:
db.execute('a sql stmt', obj.attr1)
db.execute('another sql stmt', obj.attr2)
except DBError:
db.rollback()
esle:
db.commit()
def save(db, obj):
some_error_occured = False
try:
db.execute('a sql stmt', obj.attr1)
db.execute('another sql stmt', obj.attr2)
except DBError:
db.rollback()
some_error_occurred = True
if not some_error_occured:
db.commit()

总结:本篇列举了python的一些基础语法使用建议和注意事项,慢慢消化

参考:编写高质量代码--改善python程序的91个建议

编写高质量代码--改善python程序的建议(四)的更多相关文章

  1. 编写高质量代码--改善python程序的建议(六)

    原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...

  2. 编写高质量代码--改善python程序的建议(八)

    原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...

  3. 编写高质量代码--改善python程序的建议(七)

    原文发表在我的博客主页,转载请注明出处! 建议三十四:掌握字符串的基本用法 编程有两件事,一件是处理数值,另一件是处理字符串,在商业应用编程来说,处理字符串的代码超过八成,所以需要重点掌握. 首先有个 ...

  4. 编写高质量代码–改善python程序的建议(五)

    原文发表在我的博客主页,转载请注明出处! 建议二十三:遵循异常处理的几点基本原则 python中常用的异常处理语法是try.except.else.finally,它们可以有多种组合,语法形式如下: ...

  5. 编写高质量代码--改善python程序的建议(三)

    原文发表在我的博客主页,转载请注明出处! 建议十三:警惕eval()的安全漏洞 相信经常处理文本数据的同学对eval()一定是欲罢不能,他的使用非常简单: eval("1+1==2" ...

  6. 编写高质量代码–改善python程序的建议(二)

    原文发表在我的博客主页,转载请注明出处! 建议七:利用assert语句来发现问题断言(assert)在很多语言中都存在,它主要为调试程序服务,能够快速方便地检查程序的异常或者发现不恰当的输入等,可防止 ...

  7. 编写高质量代码--改善python程序的建议(一)

    原文发表在我的博客主页,转载请注明出处! 初衷 python是一个入门十分容易的编程语言,但是想要写好python却是一件不容易的事情,如果不是专业使用python的人,只是将python作为一个脚本 ...

  8. 编写高质量代码改善python程序91个建议学习01

    编写高质量代码改善python程序91个建议学习 第一章 建议1:理解pythonic的相关概念 狭隘的理解:它是高级动态的脚本编程语言,拥有很多强大的库,是解释从上往下执行的 特点: 美胜丑,显胜隐 ...

  9. 编写高质量代码 改善Python程序的91个建议 (读后 小记)

    此书是自己好久之前买的,当时总觉得Python语言中有各种trick, 总是要自己猝不及防的掉入到陷阱之中, 看了一些资料后发现了这本书,感觉很是不错,不过可惜自己平时总是杂事太多,总是找不到整块的时 ...

随机推荐

  1. SuperMap iClient如何使用WMS地图服务

    什么是WMS服务 WMS(Web Map Service,Web 地图服务)服务,该服务符合 OGC(Open Geospatial Consortium,开放地理信息联盟)制定的 WMS 实现规范. ...

  2. Android View Attributes

    ImageView android:adjustViewBounds  Set this to true if you want the ImageView to adjust its bounds ...

  3. javascript解析器(引擎)

    The JavaScript interpreter in a browser is implemented as a single thread. javascript 引擎在浏览器中作为单线程实现 ...

  4. 开源框架AsyncHttpClient使用

    开源框架AsyncHttpClient使用 2013-10-14 15:16:35 分类: Android平台 在大神岩岩的推荐下使用了AsyncHttpClient框架,用过之后感觉还是灰常好用滴. ...

  5. js的常见函数

    var n=0.0145; n.toFixed(2);//保留两位小数 n.lastIndexOf('a');//检索字符串最后出现的位置 n.indexof("h");//检索字 ...

  6. Navicat Premium 快捷键

    1.ctrl+q 打开查询窗口2.ctrl+/ 注释sql语句3.ctrl+shift +/ 解除注释4.ctrl+r 运行查询窗口的sql语句5.ctrl+shift+r 只运行选中的sql语句6. ...

  7. spring in action第一章小结1

    1 spring基本理念是简化java开发. 使用以下4个策略简化java开发 1) 基于POJO的轻量级和最小侵入性编程 2)通过使用DI和AOP实现松耦合 3)基于切面和惯例进行声明式编程 4)通 ...

  8. unity5, UI Button "On Button Down"

    unity5自带的UI Button的Inspector面板中只有On Click事件,如果我们想让一个按钮响应On Button Down事件该怎么办呢?方法是: 点Add Component-&g ...

  9. shared-service.ts

    shared-service.ts import { Observable } from 'rxjs/Observable'; import { Injectable } from '@angular ...

  10. 多线程-Thread、Runnable、Callbale、Future

    Thread:java使用Thread代表线程,所有的线程对象都必须是Thread类或其子类,可以通过继承Thread类来创建并启动多线程. package org.github.lujiango; ...