概念:是一个闭包,把一个函数当作参数返回给一个替代版的函数,本质上就是一个返回函数的函数
将参数函数进行装饰,并将装饰好的函数返回给调用者
ps:函数重名的问题
def test1():
print(1) #开辟了一块空间,让test1指向了这块空间
def test1(): #开辟了一块空间,然后让test1改为指向这块空间。所以会面调用test1会输出2
print(2)
test1() #会输出2
#所以以后一定要自己避免函数同名的问题,因为python不会像C等语言一样提示
- 简单的装饰器
def func1():
print("sunck is a good man!")
#要求,在不改变函数的前提下修改函数的功能,使其在前面输出星号
def outerFunc(func):
def innerFunc():
print("*" * 10)
func()
return innerFunc
f = outerFunc(func1)
f() #f是func1的强加版本
- 复杂一点的装饰器
def say(age):
print("sunck is %d yeras old"%age)
say(10)
def outer(fun):
def inner(age):
if age < 10:
age = 0
fun(age)
return inner
f = outer(say)
f(-10)
@装饰器
使用@符号将装饰器应用到函数,从python2.4开始支持
def outer(fun):
def inner(age):
if age < 10:
age = 0
fun(age)
return inner
@outer #相当于say = outer(say)
def say(age):
print("sunck is %d years old"%age)
say(-10)
通用装饰器
def outerFunc(func):
def innerFunc(*args, **kwargs): #如果这里不接受参数,会导致最后一行调用say("Tom",19)失败
# 添加修饰的功能
print("*" * 10)
return func(*args, **kwargs) #如果参数函数有返回值,则再将其返回值返回。如果这里不接受参数,会导致执行say函数时失败,因为say函数的定义部分明确指定;要两个参数。同时,这里参数前面的“*”是对传递进来的参数解包,因为其传递进来后,其分别是以元组和字典的形式保存的,所以需要解包成原来的形式后再传进行传递。
#如果在内部执行func后还有其他修饰,可以用变量对func的执行后的结果进行保存,然后在innerFunc的最后将该变量进行返回
return innerFunc
@outerFunc
def say(name, age):
print("my name is %s, my age is %d"%(name, age))
say("Tom", 19)
ps:函数的参数理论上不限制个数,但是实际上不宜超过6-7个
多个装饰器
对于多个装饰器,先加后装饰,但是调用时的顺序同装饰时的顺序
def makeBold(fn):
print("正在装饰1")
def wrapped():
print("1".center(10, "-"))
return "<b>" + fn() + "<b>"
return wrapped
def makeItalic(fn):
print("正在装饰2")
def wrapped():
print("2".center(10, "-"))
return "<i>" + fn() + "<i>"
return wrapped
@makeBold
@makeItalic
def test3():
print("3".center(10, "-"))
return "hello wold-3"
ret = test3() #程序执行test3的时候,先是test3 = makeBold(test3),然后执行test3,但是在makeBold里面的执行return语句时会调用fn(即test3),然后再次以装饰器的形式调用。所以先加的装饰器后装饰。
print(ret)
#输出如下:
正在装饰2
正在装饰1
----1-----
----2-----
----3-----
ps
:装饰器什么时候进行装饰?
当使用@的时候已经开始装饰了,相当于执行被装饰的函数 = 用于装饰的函数(被装饰的函数)
带参数的装饰器
作用:在运行时,根据不同的情况对函数进行不同的装饰
from time import ctime,sleep
def timefun_arg(pre="hello"):
def timefunc(func):
def wrappedfunc():
print("%s called at %s %s"%(func.__name__,ctime(),pre))
return func()
return wrappedfunc
return timefunc
@timefun_arg("itcast") #1、先执行timefun_arg("heihei")这个函数,这个函数return的结果是timefunc这个函数的引用。2、@timefunc。3、使用@timefunc对foo进行装饰
def foo():
print("I am foo")
@timefun_arg("python")
def too():
print("I am too")
foo()
sleep(2)
too()
翻外之偏函数
print(int("1010",base=2)) #输出10
#偏函数
*其实就是对函数参数上默认值的控制,个人理解,因为对函数的参数有偏向性,所有叫偏函数*
def int2(str,base = 2):
return int(str,base)
print(int("1011"))
偏函数理论上不需要自己定义
import functools
此模块可以帮助构建偏函数
int3 = functools.partial(int,base=2)
其实是把一个参数固定住,形成一个新的函数
格式:新函数名=functools.partial(函数名,要固定的参数=所固定的参数值)
变量的作用域
def:作用域即变量可以使用的范围
程序的变量并不是现在所有的位置的能够使用的,访问的权限取决于变量的位置,即变量在哪里定义的
- 作用域:
- 局部作用域
- 全局作用域
- 内建作用域
常用的两种:局部和全局