首页 > 代码库 > python装饰器、模块
python装饰器、模块
python装饰器
装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器语法简单,代码可读性高。因此,装饰器在Python项目中有广泛的应用。
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用函数,假设我们要增强函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),decorator就是一个返回函数的高阶函数。
装饰器方法
- 先定义一个简单的函数,计算平方和
# get square sum def square_sum(a, b): return a**2 + b**2
print(square_sum(3, 4))
如果要为square_sum()函数添加打印功能,修改后的写法如下:
# get square sum def square_sum(a, b): print("intput:", a, b) return a**2 + b**2
print(square_sum(3, 4)
使用装饰器实现修改:
def decorator(F): def new_F(a, b): print("input", a, b) return F(a, b) return new_F
# get square sum @decorator def square_sum(a, b): return a**2 + b**2
print(square_sum(3, 4))
def decorator(F): def new_F(a, b): print("input", a, b) return F(a, b) return new_F
# get square sum @decorator def square_sum(a, b): return a**2 + b**2
print(square_sum(3, 4))
装饰器可以用def的形式定义,如上面代码中的decorator。装饰器接收一个可调用对象作为输入参数,并返回一个新的可调用对象。装饰器新建了一个可调用对象,也就是上面的new_F。new_F中,我们增加了打印的功能,并通过调用F(a, b)来实现原有函数的功能。
定义好装饰器后,可以通过@语法使用了。在函数square_sum定义之前调用@decorator,实际上将square_sum传递给decorator,并将decorator返回的新的可调用对象赋给原来的函数名(square_sum)。 所以,当调用square_sum(3, 4)的时候,就相当于:
square_sum = decorator(square_sum) square_sum(3, 4)
从本质上,装饰器起到的就是这样一个重新指向变量名的作用(name binding),让同一个变量名指向一个新返回的可调用对象,从而达到修改可调用对象的目的,如果有其他的类似函数,可以继续调用decorator来修饰函数,而不用重复修改函数或者增加新的封装。
含参的装饰器
装饰器调用中,比如@decorator,该装饰器默认它后面的函数是唯一的参数。装饰器的语法允许我们调用decorator时,提供其它参数,比如@decorator(a)。
# a new wrapper layer def pre_str(pre=‘‘): # old decorator def decorator(F): def new_F(a, b): print(pre + "input", a, b) return F(a, b) return new_F return decorator # get square sum @pre_str(‘hello‘) def square_sum(a, b): return a**2 + b**2
上面的pre_str是允许参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有环境参量的闭包。
当我们使用@pre_str(‘hello‘)调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。该调用相当于
square_sum = pre_str(‘hello‘) (square_sum)
python模块、包
1、import语句
在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入,语法如下:
import module1[, module2[,... moduleN]
model.py语句
def run():
print(‘这个是当前目录下的,这是在model里面的run函数‘)
def run1():
print(‘run1‘)
def run2():
print(‘run2..‘)
name = 5print(‘66666‘)
model2.py语句
import model
model.run1()
model.run2()
model.run()
输出:
66666
test
run1
run2..
这个是当前目录下的,这是在model里面的run函数
说明:import的本质就是把这个python文件从头到尾执行一遍
2、from…import 语句
Python的from语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
from modname import name1[, name2[, ... nameN]]
from model import run,run1
run()
run1()
输出:
66666
这个是当前目录下的,这是在model里面的run函数
run1
3、From…import* 语句
把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:
from modname import *
注:从一个模块里面导入所有的函数,不建议过多使用。
4、搜索路径和路径搜索
模块的导入需要叫做“路径搜索”的过程。
搜索路径:查找一组目录
路径搜索:查找某个文件的操作
Python搜索模块的路径:
1)、程序的主目录
2)、PTYHONPATH目录(如果已经进行了设置)
3)、标准连接库目录(一般在/usr/local/lib/python2.X/)
4)、任何的.pth文件的内容(如果存在的话).新功能,允许用户把有效果的目录添加到模块搜索路径中去
ImportError: No module named myModule,这种错误就是说:模块不在搜索路径里,从而导致路径搜索失败!
解决方法:1、在调用文件中添加sys.path.append("模块文件目录");
2、使用pth文件,在 site-packages 文件中创建 .pth文件,将模块的路径写进去,一行一
个路径,以下是一个示例,pth文件也可以使用注释:
# .pth file for the my project(这行是注释),命名为xxx.pth文件
C:\Users\Administrator\Desktop\test
5、包
包是一种管理 Python 模块命名空间的形式,采用"点模块名称",比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B ,如:
import sound.effects.echo
包和文件夹的区别就是包下面有个__init__.py,在python2里面,如果你要导入其他文件夹下面的python文件,那么必须是一个包
python3不需要,只是文件夹就行了
python装饰器、模块