Python下的匿名函数,及装饰器(解释器为python3.6)

一.Python下的匿名函数

1.匿名函数的语法规则:

匿名函数(一般作为参数写到别人定义的函数中去,目的:变为动态的代码):用lambda关键字能创建小型的匿名函数,这种函数省略了def的声明。
其语法为:lambda [args1[,args2,args3...]]:expression(表达式)————即可以接多个参数,而后面只允许接表达式。冒号前面是形参,冒号后面是返回值。


def test(a,b):
     return a+b
print(test(22,33))        #输出55

f=lambda x,y:x+y
print(f(22,33))           #输出55

2.匿名函数的应用:

<1>应用一:

匿名函数的应用1
def test(a,b,func):
    result=func(a,b)
    return result
print(test(22,33,lambda x,y:x*y))               #输出726

<2>应用二:

匿名函数的应用2
#下面的代码有错误(列表的字典之间不能比大小
# stus=[{'name':'zs','age':22},{'name':'老王','age':33},{'name':'aini','age':18}]
# stus.sort()                     #输出报错

stus=[{'name':'zs','age':22},{'name':'老王','age':33},{'name':'aini','age':18}]
stus.sort(key=lambda x:x['age'])
print(stus)                  #输出[{'name': 'aini', 'age': 18}, {'name': 'zs', 'age': 22}, {'name': '老王', 'age': 33}]

<3>应用三:

匿名函数的应用3(关于python动态语言的应用)
#在python3中不能跑下面的程序(这是因为python3的input将输入的东西当作字符串,而python2中input将输入的东西当作表达式,raw_input将输入的东西当作表达式。
def test(a,b,func):
    result=func(a,b)
    return result
while True:

    func_new=input('请输入你的操作:')
    print(test(22,33,func_new))

#在python3中也能跑
def test(a,b,func):
    result=func(a,b)
    return result
while True:
    func_new=input('请输入你的操作:')
    func_new=eval(func_new)             #把字符串转换成可以执行的表达式。
    print(test(22,33,func_new))

3.匿名函数的参数:

<1>匿名函数的默认参数

f=lambda x,y=2:x**y
print(f(2))                  #输出4
print(f(2,4))              #输出16

<2>匿名函数的可变参数

f=lambda *args:sum(args)
print(f(1,2,3,4,5,6))         #输出21

<3>匿名函数的关键字参数

f=lambda **kwargs:kwargs.keys()
print(f(name='fentiao',age=10))      #输出dict_keys(['name', 'age'])

f=lambda **kwargs:kwargs.values()
print(f(name='fentiao',age=10))      #输出dict_values(['fentiao', 10])

4.匿名函数的练习:

<1>练习一:

计算1+2+3+4+5的和

from functools import reduce
print(reduce(lambda x,y:x+y,[1,2,3,4,5]))

<2>练习二:

计算1的平方,2的平方,3的平方,4的平方,5的平方,并将其放入一个列表中

print(list(map(lambda x:x**2,range(1,6))))

<3>练习三:

计算10的阶乘

from functools import reduce
print(reduce(lambda x,y:x*y,range(1,11)))

<4>练习四:

(2018-携程-春招题)题目需求:
给定一个整形数组, 将数组中所有的0移动到末尾, 非0项保持不变;
在原始数组上进行移动操作, 勿创建新的数组;
# 输入:
    第一行是数组长度, 后续每一行是数组的一条记录;
    4
    0
    7
    0
    2
# 输出:
    调整后数组的内容;
    4
    7
    2
    0
    0

#方法一:
nums=[0,7,0,1,2,1,5,1,7,8,0,67,1,3,4]         #输出[7, 1, 2, 1, 5, 1, 7, 8, 67, 1, 3, 4, 0, 0, 0]
print(sorted(nums,key=lambda x:1 if x==0 else 0))   #输出[7, 1, 2, 1, 5, 1, 7, 8, 67, 1, 3, 4, 0, 0, 0]



#方法二:
nums=[0,7,0,1,2,1,5,1,7,8,0,67,1,3,4]         #输出[7, 1, 2, 1, 5, 1, 7, 8, 67, 1, 3, 4, 0, 0, 0]
print(sorted(nums,key=lambda x: x==0))   #输出[7, 1, 2, 1, 5, 1, 7, 8, 67, 1, 3, 4, 0, 0, 0]

二.Python下的装饰器

1.装饰器的含义:

装饰器:其实就是一个闭包,对外函数传入参数(该参数是一个函数),然后定义的内部函数对传进来的参数(函数)进行封装。然后再把封装好的内部函数作为返回值返回。

2.装饰器的语法规则:

<1>装饰器基础之无参:

def decorator(func):              #固定格式
    def wrapper():
        print('~~~~')
        func()
    return wrapper
@decorator                    #语法糖,表示在执行fun1函数之前,先执行装饰器
def func1():
    print('hello python')

func1()
#输出   ~~~~
#      hello python

 

当然也可以不写成语法糖。

def decorator(func):
    def wrapper():
        print('~~~~')
        func()
    return wrapper

def func1():
    print('hello python')

f=decorator(func1)
f()

#输出   ~~~~
#      hello python

<2>装饰器基础之无参:

import time                         #导入时间模块

def decorator(func):
    def wrapper():
        print(time.time())
        func()
    return wrapper

@decorator
def func1():
    print('This is a function')

func1()
#输出   1547965843.6613572
#           This is a function

<3>装饰器基础之一个参数:

import time

def decorator(func):
    def wrapper(args):
        print(time.time())
        func(args)
    return wrapper

@decorator
def func1(func_name):
    print('This is function ' + func_name)

func1('test')
#输出  1547965902.3124943
#     This is function test

<4>装饰器基础之多个参数(可变参数):

import time

def decorator(func):
    def wrapper(*args):
        print(time.time())
        func(*args)
    return wrapper

@decorator
def func1(func_name1,func_name2):
    print('This is function ' + func_name1)
    print('This is function ' + func_name2)

func1('test1','test2')
#输出   1547965947.4943426
#      This is function test1
#      This is function test2

<5>装饰器基础之关键字参数:

import time
def decorator(func):
    def wrapper(*args,**kwargs):
        print(time.time())
        func(*args,**kwargs)
    return wrapper

@decorator
def func1(func_name1,func_name2,**kwargs):
    print('This is function ' + func_name1)
    print('This is function ' + func_name2)
    print(kwargs)

func1('test1','test2',a=1,b=2,c=3)
#输出   1547965741.7117374
#      This is function test1
#      This is function test2
#      {'a': 1, 'b': 2, 'c': 3}

<6>装饰器基础之函数带有返回值:

import time

def decorator(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        end_time=time.time()
        print('运行时间为:%.6f' %(end_time-start_time))
        return res
    return wrapper

@decorator
def fun_list(n):
    return [i*2 for i in range(n)]

@decorator
def fun_map(n):
    return list(map(lambda x:x*2,range(n)))

print(fun_list(50))       #值的注意的是:如果前面的装饰器中不加return res  那么打印出来的列表是none
print(fun_map(50))     #值的注意的是:如果前面的装饰器中不加return res  那么打印出来的列表是none

#输出   运行时间为:0.000009
#      [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]
#      运行时间为:0.000011
#      [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98]

3.装饰器的练习:

<1>练习一:装饰器实现一个函数计时器

import time
import random
import functools
import string

#问题一:如何保留被装饰函数的函数名和帮助文档
li=[random.choice(string .ascii_letters)  for  i  in  range(100)]

def decorator(func):
    """这是一个wrapper函数"""
    @functools.wraps(func)
    def wrapper():
        start_time=time.time()
        func()
        end_time=time.time()
        print('运行时间为:%.6f' %(end_time-start_time))
    return wrapper

@decorator

def con_add():
    '''这是for循环实现拼接'''
    s=''
    for i in li:
        s+=(i+',')
    print(s)
@decorator
def join_add():
    print(','.join(li))

con_add()
join_add()
#输出     M,D,x,z,w,f,Z,y,b,b,p,K,C,c,a,g,h,i,W,F,J,T,V,X,t,a,F,l,G,I,X,I,A,c,X,W,P,c,o,l,j,h,m,R,g,w,L,

               w,R,j,L,i,u,t,t,v,u,F,K,z,d,m,p,R,l,Z,X,F,x,t,J,Y,I,u,e,N,v,A,h,u,M,e,c,T,r,P,V,l,A,n,S,B,H,h,T,f,d,F,N,W,
#            运行时间为:0.000074
#             M,D,x,z,w,f,Z,y,b,b,p,K,C,c,a,g,h,i,W,F,J,T,V,X,t,a,F,l,G,I,X,I,A,c,X,W,P,c,o,l,j,h,m,R,g,w,L,w,R,j,L

              ,i,u,t,t,v,u,F,K,z,d,m,p,R,l,Z,X,F,x,t,J,Y,I,u,e,N,v,A,h,u,M,e,c,T,r,P,V,l,A,n,S,B,H,h,T,f,d,F,N,W
#            运行时间为:0.000012
print(con_add.__doc__)
print(join_add.__doc__)             #值的注意的是:如果前面的装饰器中不加 @functools.wraps(func),那么打印出来的是wrapper函数的注释(这是一个wrapper函数
print(con_add.__name__)        #值的注意的是:如果前面的装饰器中不加 @functools.wraps(func),那么打印出来的名字是wrapper
print(join_add.__name__)
#输出   运行时间为:0.000008
#          这是for循环实现拼接
#          None
#         con_add
#         join_add

<2>练习二

 创建装饰器, 要求如下:
# 1. 创建add_log装饰器, 被装饰的函数打印日志信息;
# 2. 日志格式为: [字符串时间] 函数名: xxx,运行时间:xxx,运行返回值结果:xxx

import time
import functools

def add_log(func):
    @functools .wraps(func)
    def wrapper(*args):
        start_time=time.time()
        res=func(*args)
        end_time=time.time()
        print('[%s] 函数名:%s,运行时间:%.6f,运行返回值结果:%s' \
             %(time.ctime(),func.__name__,(end_time-start_time),res))
        # return res
    return wrapper

@add_log
def add(x,y):
    time.sleep(1)
    return x+y

# print(add(1,10))
add(1,10)

<3>练习三

编写装饰器实现,如果是root用户就能执行add函数,如果不是root用户就输出“不是root用户,不能添加用户”

import inspect
def decorator(func):
    def wrapper(args):
        #inspect.getcallargs返回值是字典,key值为:形参,value值为形参对应的实参
        inspect_res=inspect.getcallargs(func,args)
        print('inspect_res的返回值为:%s' %inspect_res)
        if inspect_res.get('name')=='root':
            func(args)
        else:
            print('你不是root用户,不能添加用户')
    return wrapper

@decorator
def add_student(name):
    print('添加学生信息...')

add_student('root')
#输出结果:   inspect_res的返回值为:{'name': 'root'}
#           添加学生信息...
add_student('xin')
#输出结果:    inspect_res的返回值为:{'name': 'xin'}
#            你不是root用户,不能添加用户

这里值的注意的是inspect模块的使用。

<4>练习四

编写装饰器required_ints, 条件如下:
    1). 确保函数接收到的每一个参数都是整数;  # 如何判断变量的类型?
     type(s), isinstance(s,str)
    2). 如果参数不是整形数, 抛出异常raise TypeError(“参数必须为整形”)

def required_ints(func):
    def wrapper(*args,**kwargs):
        for i in args+tuple(kwargs.values()):
            if not isinstance(i,int):
                raise TypeError('参数必须为整型')
        return func(*args,**kwargs)
    return wrapper
@required_ints
def add(*args,**kwargs):
    # return sum(args)+sum(kwargs.values())
    return sum((args+tuple(kwargs.values())))

print(add(1,2,3,65,67,1,a=1,b=2))
print(add(1,2,3,65,67,1.0,a=1,b=2))

<5>练习五:装饰器传入参数

def required_types(*kinds):
    def required_ints(func):
        def wrapper(*args):
            for i in args:
                if not isinstance(i,kinds):
                    # raise TypeError('参数必须为整型')
                    print('TypeError:参数必须为:',kinds)
                    break
            else:
                return func(*args)
        return wrapper
    return required_ints

@required_types(int)
def add(*args):
    return sum(args)
print(add(1,2,4,5,6))
#      输出 18
print(add(1,2,4.0,5,6))
#     输出  TypeError:参数必须为: (<class 'int'>,)
#     None

<6>练习六:装饰器的执行顺序

def decorator_a(func):
    print('Get in decorator_a')
    def inner_a(*args,**kwargs):
        print('Get in inner_a')
        res = func(*args,**kwargs)
        return res
    return inner_a

def decorator_b(func):
    print('Get in decorator_b')
    def inner_b(*args,**kwargs):
        print('Get in inner_b')
        res = func(*args,**kwargs)
        return res
    return inner_b


@decorator_b
@decorator_a

def f(x):
    print('Get in f')
    return x * 2

print(f(1))
#输出  Get in decorator_a
#          Get in decorator_b
#          Get in inner_b
#          Get in inner_a
#          Get in f
#          2

import inspect
def decorator_login(func):
    def wrapper(args):
        if args in login_list:
            print('登陆成功')
            res=func(args)
        else:
            print('登陆失败')
    return wrapper
def decorator(func):
    def wrapper(args):
        inspect_res=inspect.getcallargs(func,args)
        print('inspect_res的返回值为:%s' %inspect_res)
        if args=='root':
            func(args)
        else:
            print('你不是root用户,不能添加用户')
    return wrapper
login_list=['root','admin','redhat']
@decorator_login
@decorator

def add_student(name):
    print('添加学生信息...')

add_student('admin')
#输出  登陆成功
#         inspect_res的返回值为:{'name': 'admin'}
#         你不是root用户,不能添加用户
add_student('root')
#输出   登陆成功
#          inspect_res的返回值为:{'name': 'root'}
#          添加学生信息...
add_student('xin')
#输出   登陆失败

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值