python匿名函数,闭包,装饰器,偏函数

本文详细介绍了Python中的匿名函数,包括lambda表达式的使用,以及在map和sorted等操作中的应用。接着探讨了闭包的概念、创建和使用,展示了闭包在不修改源代码的情况下添加新功能的能力。进一步,文章讲解了装饰器的原理和用法,包括带参数的装饰器和多个装饰器的叠加。最后,提到了偏函数在简化函数调用中的作用,通过functools.partial实现固定参数的功能。
摘要由CSDN通过智能技术生成

匿名函数

在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。 Python 中,对匿名函数提供了支持。计算 f(x)=x2 时,除了定义一个 f(x) 的函数外,
还可以直接传入匿名函数。使用 lambda 可以声明一个匿名函数。 lambda 表达式就是一个简单的函数。使用 lambda 声明的函数可以返回一个值,在调用
函数时,直接使用 lambda 表达式的返回值。使用 lambda 声明函数的语法格式如下。
lambda arg1,arg2,arg3... : < 表达式 >
其中 arg1/arg2/arg3 为函数的参数。 < 表达式 > 相当于函数体。运算结果是:表达式的运 算结果
匿名函数有个限制,就是只能有一个表达式,不用写 return ,返回值就是该表达式的结 果。
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是 一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数

lambda 表达式使用

# lambda arg1,arg2,arg3...:表达式
f=lambda a,b,c:a+b+c
print('调用:',f(3,4,5))

调用: 12

匿名函数实现 f(x)=x*x 

#匿名函数作为map高阶函数的参数  f(x)=x*x
L=map(lambda x:x*x,[1,2,3,4,5,6,7,8,9])
print(list(L))

[1, 4, 9, 16, 25, 36, 49, 64, 81]

sorted 对自定义对象进行排序

#sorted中使用匿名函数
class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age

stu1=Student('zhangsan',21)
stu2=Student('lisi',25)
stu3=Student('wangwu',23)
# result_list=sorted([stu1,stu2,stu3],key=lambda x:x.age)
result_list=sorted([stu1,stu2,stu3],key=lambda x:x.name,reverse=True)
for stu in result_list:
    print('name:',stu.name,'age:',stu.age)

name: zhangsan age: 21
name: wangwu age: 23
name: lisi age: 25
 

闭包

 
根据字面意思,可以形象地把闭包理解为一个封闭的包裹,这个包裹就是一个函数。当 然,还有函数内部对应的逻辑,包裹里面的东西就是自由变量,自由变量可以随着包裹到处
游荡。还需要有个前提,这个包裹是创建出来的。在 Python 语言中,闭包意味着要有嵌套 定义,内部函数使用外部函数中定义的变量,如果调用一个函数 A ,这个函数 A 返回一个
函数 B ,这个返回的函数 B 就叫作闭包。
1.什么是闭包
   闭包其实就是一个函数
2.如何创建闭包
  a.要有函数的嵌套(外部函数、内部函数)
  b.内部函数中要使用外部函数的变量
  c.外部函数必须有返回值,返回内部函数名
3.如何使用闭包
    f=funOut(100)   #调用外部函数,用f变量指向内部函数
    print(type(f))
    result=f(200)    #通过变量调用函数
#使用闭包,完成求两个数的和
def sum(a,b):
    return a+b

def funOut(num1):
    def funIn(num2):
        #内部函数修改外部函数的变量
        nonlocal num1
        num1+=100
        return num2+num1
    return funIn

funIn=funOut(100)
print(type(funIn))
result=funIn(200)
print('两个数的和:',result)

<class 'function'>
两个数的和: 400

 求两点之间的距离

#使用闭包求两点之间的距离
'''
   两个点  (x1,y1)  (x2,y2)
   距离: math.sqrt((x1-x2)**2+(y1-y2)**2)
'''
import math
def getDis(x1,y1,x2,y2):
    return math.sqrt((x1-x2)**2+(y1-y2)**2)
#求点(1,1)距离原点(0,0)的距离
result=getDis(1,1,0,0)
print('点(1,1)距离原点(0,0)的距离',result)

#求点(2,2)距离原点(0,0)的距离
result=getDis(2,2,0,0)
print('点(2,2)距离原点(0,0)的距离',result)

#使用闭包求两点之间的距离
def getDisOut(x1,y1):
    def getDisIn(x2,y2):
        return math.sqrt((x1-x2)**2+(y1-y2)**2)
    return getDisIn

#求点(1,1)距离原点(0,0)的距离
#调用外部函数
getDisIn=getDisOut(0,0)
result=getDisIn(1,1)
print('点(1,1)距离原点(0,0)的距离',result)

#求点(2,2)距离原点(0,0)的距离
result=getDisIn(2,2)
print('点(2,2)距离原点(0,0)的距离',result)

点(1,1)距离原点(0,0)的距离 1.4142135623730951
点(2,2)距离原点(0,0)的距离 2.8284271247461903
点(1,1)距离原点(0,0)的距离 1.4142135623730951
点(2,2)距离原点(0,0)的距离 2.8284271247461903

闭包的特殊用途:不修改源代码的前提下,添加新的功能

#闭包的特殊用途:不修改源代码的前提下,添加新的功能
#添加日志输出信息
import time
def writeLog(func):
    try:
        file=open('wirteLog.txt','a',encoding='utf-8')
        #向文件中写入日志信息(访问:方法名  时间:XXXX-XX-XX)
        file.write('访问:')
        file.write(func.__name__)
        file.write('\t')
        file.write('时间:')
        file.write(time.asctime())
        file.write('\n')
    except Exception as e:
        print(e.args)
    finally:
        file.close()
def fun1():
    # writeLog(fun1)
    print('功能1')
def fun2():
    # writeLog(fun2)
    print('功能2')

#使用闭包,不修改fun1  和fun2的功能代码,添加日志信息
def funcOut(func):
    def funcIn():
        writeLog(func)
        func()
        print('调用',func.__name__,'结束')
    return funcIn

fun1=funcOut(fun1)
fun1()
fun2=funcOut(fun2)
fun2()

 功能1
调用 fun1 结束
功能2
调用 fun2 结束

装饰器 

python 程序中,装饰器就是一种闭包,它可以是闭包的访问方式更简单。
#使用装饰器 完成不修改fun1() fun2()函数的源码,添加输出日志信息
import time

def writeLog(func):
    try:
        file=open('log.txt','a',encoding='utf-8')
        file.write('访问:')
        file.write(func.__name__)
        file.write('\t')
        file.write('时间:')
        file.write(time.asctime())
        file.write('\n')
    except Exception as e:
        print(e.args)
    finally:
        file.close()

#使用闭包
def funcOut(func):
    def funcIn():
        writeLog(func)
        func()
    return funcIn
#闭包的调用

@funcOut  #fun1=funcOut(fun1)
def fun1():
    print('功能1')

@funcOut
def fun2():
    print('功能2')
fun1()
fun2()

功能1
功能2 

多个装饰器 

#给foo函数,新增功能
#在调用foo函数前,输出 ’I am foo‘
def funOut(func):
    print('装饰器1')
    def funIn():
        print('I am foo')
        func()
    return funIn

def funOut2(func):
    print('装饰器2')
    def funIn():
        print('hello')
        func()
    return funIn

@funOut2
@funOut
def foo():
    print('foo函数正在运行')

#使用闭包调用
# foo=funOut(foo)
foo()

装饰器1
装饰器2
hello
I am foo
foo函数正在运行

带参数的装饰器 

import time
def writeLog(func):
    print('访问了方法名:',func.__name__,'\t时间:',time.asctime())

def funOut(func):
    def funIn(x,y):
        writeLog(func)
        return func(x,y)
    return funIn

@funOut
def sum(a,b):
    return a+b

result=sum(10,20)
print('两数的和:',result)

#功能函数三个参数
def funOut2(func):
    def funcIn(a,b,c):
        writeLog(func)
        return func(a,b,c)
    return funcIn
@funOut2
def add(a,b,c):
    return a+b+c

result=add(10,20,30)
print('三个数的和:',result)

访问了方法名: sum     时间: Sat Oct 31 21:43:44 2020
两数的和: 30
访问了方法名: add     时间: Sat Oct 31 21:43:44 2020
三个数的和: 60

通用装饰器 

*args 可变参数,**kwargs字典形式

import time
def funcOut(func):
    def funcIn(*args,**kwargs):
        writeLog(func)
        return func(*args,**kwargs)
    return funcIn

def writeLog(func):
    print('访问方法名:',func.__name__,'\t时间:',time.asctime())

@funcOut
def sum(a,b):
    return a+b

@funcOut
def add(a,b,c):
    return a+b+c

result=sum(10,20)
print('两个数的和:',result)
result=add(10,20,30)
print('三个数的和:',result)

访问方法名: sum     时间: Sat Oct 31 22:04:09 2020
两个数的和: 30
访问方法名: add     时间: Sat Oct 31 22:04:09 2020
三个数的和: 60

偏函数 

Python functools 模块提供了很多有用的功能,其中一个就是偏函数( Partial function )。
要注意,这里的偏函数和数学意义上的偏函数不一样。
偏函数是用于对函数固定属性的函数,作用就是把一个函数某些参数固定住(也就是设
置默认值),返回一个新的函数,调用这个新的函数会更简单。
在介绍函数参数的时候,我们讲到,通过设定参数的默认值,可以降低函数调用的难度。
而偏函数也可以做到这一点
print(int('12345')) #将字符串按十进制转换为整数
print('转换为八进制:',int('12345',base=8))
print('转换为十六进制:',int('12345',16))
#将'1010' 按二进制转换为整数
print(int('1010',base=2))
print(int('101010',base=2))
print(int('10101010',base=2))
#定义函数
def new_int(s):
    return int(s,base=2)
print(new_int('1010'))
print(new_int('101010'))
print(new_int('10101010'))

from functools import partial
new_int=partial(int,base=2)
print(new_int('1010'))
print(new_int('101010'))
print(new_int('10101010'))

12345
转换为八进制: 5349
转换为十六进制: 74565
10
42
170
10
42
170
10
42
170
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值