Python 模块,包,分发
首次使用import加载模块时,将会做三件事:
1.创建新的命名空间,用作在相应源文件中定义的左右对象的容器。在模块中定义的函数和方法在使用global语句时将访问该命名空间。
2.在新创建的命名空间中执行模块中包含的代码。
3.在调用函数中创建名称来引用模块命名空间。
需要注意的是,import执行已加载源的文件中的所有语句。引用模块的名称可以使用as限定符进行更改,使用其他名称加载模块时,新名称仅应用于出现了import语句的源文件或上下文。其他程序模块仍然可以使用模块原来的名称加载它。
import语句可以出现在程序中的任何位置,但是,每个模块代码仅加载和执行一次,无论import语句被使用了多少次,后续的import语句仅将模块名称绑定到前一次导入所创建的模块对象。
*通配符可用于加载模块中的所有定义,下划线开头的定义除外。
*语句只能在模块最顶层使用,在函数体中使用这种导入形式是不合法的,原因在于这种导入语句与函数作用域规则之间具有独特的交互方式。
模块搜索路径
加载模块时,解释器在sys.path路径中搜索字典列表。sys.path中的第一条目通常是一个空字符串 ‘ ’,表示当前正在使用的字典。sys.path中的其他条目可能包含字典名称、.zip归档文件和.egg文件。各个条目在sys.path中列出的顺序决定了加载模块时的搜索顺序。
包
只要第一次导入包的任何部分,就会执行文件init.py中的代码。这个文件可以为空,但也可以包含可执行特定于该包的初始化工作的代码。在import语句执行期间,遇到的所有init.py文件都会执行。
输入和输出
Python启动时,命令行选项放置在列表sys.argv中。
调优策略
1.理解程序
进行任何优化之前,需要知道通过优化程序某个部分所获得的加速与该部分所占的执行时间直接相关。如果你将一个函数运行速度提高10倍,但是该函数的执行时间仅占程序总执行时间的10%,那么仅能获得9%-10%的总体加速,有的时候得不偿失。
2.理解算法
即使最糟糕的O(nlogn)算法实现也会比经过最优化的O(n^3)算法性能要高。不要优化低效的算法,首先应该查找更好的算法。
3.使用内置类型
Python内置的元组、列表、集合和字典类型完全时用C实现的,而且时解释器中经过最好优化的数据结构。应该积极的使用这些类型来存储和操作程序中的数据,尽量避免构建自定义的数据结构来模仿他们的功能。
还用该积极的使用标准库的类型,一些库模块提供的新类型在处理特定任务上比内置类型性能更高。
4.不要添加层
任何时候向对象或函数添加额外的抽象或遍历层,都会降低程序的运行速度。但是需要在可用性和性能之间进行权衡。
s = dict(name='GOOF',share=100,price=190.10)#第一种
s = {'name':'GOOF','share':100,'price':190.10}#第二种
使用第一种这种方式创建字典来节省键入操作,运行速度会非常慢
timeit("s = {'name':'GOOF','share':100,'price':190.10}")
>>0.3891730
timeit("s = dict(name='GOOF',share=100,price=190.10)")
>>0.944200038
5.了解如何基于字典构建类和实例
用户定义的类和实例使用字典构建的,因此查找、设置、删除实例数据的速度几乎总是比直接在字典上执行这些操作更慢。如果要做的知识构建一个简单的数据结构来存储数据,字典可能是比定义一个类更有效的选择。
class Stock(object):
def __init__(self,name,shares,price):
self.name = name
self.shares = shares
self.price = price
如果比较使用该类与使用字典的性能,结果会非常有趣
from timeit import timeit
time("s = Stock('GOOG',100,490.10)","from stock import Stock")
>>1.3166780471
timeit("s = {'name':'GOOF','share':100,'price':190.10}")
>>0.23622
此处加速约为1.2,可以使用class定义新对象,但这并不是处理数据的唯一方式。元组和字典通常就够用了。使用他们会使愁绪运行更快并占用更少内存
6.使用--slots--
如果程序创建了用户定义类的大量实例,可以考虑在类定义中使用--slots--属性
class Stocks(object):
__slotd__ = ['name','shares','price']
def __init__(self,name,shares,price):
self.name = name
self.shares = shares
self.price = price
--slots--有时会被看作是一种安全功能,因为他会限制属性的名称的设置。但是,它主要的用途是性能优化。使用--slots--的类不适用字典存储实例数据(而是使用一种更高效的内部数据结构)
7.避免使用(.)运算符
使用(.)在对象查找属性时,总会涉及名称查找。例如x.name,将会在环境中查找变量x,然后再x中查找属性name。对于用户定义对象,属性查找还涉及再实例字典,类字典和基类字典中查找。
对于大量使用方法或模块查找的计算,最好首先将要执行的操作放在一个局部变量中,从而避免属性查找。如:若执行大量平方根的操作,使用from math import sqrt和sqrt(x)比键入math.sqrt(x)更快。
8.使用异常处理不常见的情况
def parse_header(line):
fields = line.split(":")
if len(fields) != 2:
raise RuntimeError("Malformed header")
header,value = fields
return header.lower(),value.strip()
def parse_header(line):
fields = line.split(":")
try:
header,value = fields
return header.lower(),value.strip()
except ValueError:
raise RuntimeError("Malformed header")
如果在格式正确的行上对他们进行测试,会发现第二个代码运行速度快10%左右。为在正常情乱下不会抛出异常的代码设置try代码块,通常会比执行if语句的速度更快。
9.避免对常见情况使用异常
不要在代码中对常见情况进行异常处理.例如,假设一个程序执行了大量字典查找,但大部分都是在查找不存在的建
try:
value = items[key]
except KeyError:
value = None
if key in items:
value = items[key]
else:
value = None
假设没有找到所需的建,第二种方法的运行速度是第一种的17倍,因为in运算符的执行速度比方法调用更快。
10 鼓励使用函数编程和迭代
列表包含、生成器、协程和闭包比大多数Python程序员想的更高效。
浙公网安备 33010602011771号