Python19_装饰器

概念:是一个闭包,把一个函数当作参数返回给一个替代版的函数,本质上就是一个返回函数的函数

将参数函数进行装饰,并将装饰好的函数返回给调用者

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:作用域即变量可以使用的范围

程序的变量并不是现在所有的位置的能够使用的,访问的权限取决于变量的位置,即变量在哪里定义的

  • 作用域:
  1. 局部作用域
  2. 全局作用域
  3. 内建作用域

常用的两种:局部和全局

猜你喜欢

转载自blog.csdn.net/qq_34873298/article/details/89601522