0
点赞
收藏
分享

微信扫一扫

Python3学习11--装饰器及偏函数

闲鱼不咸_99f1 2022-01-27 阅读 66

本系列博文基于廖雪峰老师的官网Python教程,笔者在大学期间已经阅读过廖老师的Python教程,教程相当不错,官网链接: 廖雪峰官方网站.请需要系统学习Python的小伙伴到廖老师官网学习,笔者的编程环境是Anaconda+Pycharm,Python版本:Python3.



1.装饰器

# 函数是一个对象,函数对象可以被赋值给变量,即通过变量可以调用该函数;
def time():
    print("1min.")
    
    
f = time
print("通过变量调用函数:")
f()

# 函数对象有一个__name__属性,可以拿到函数的名字;
print("通过name属性,得到函数的名字为:",time.__name__)
print("变量通过name属性,可以得到函数的名字:",f.__name__)
print("------------------------------------------------------------------")

# 增强time()函数的功能,如:在函数调用前后自动打印日志,
# 但不希望修改time()函数的定义,这种在代码运行期间动态增加功能的方式,称为"装饰器(Decorator)";

# 定义一个能打印日志的decorator:
def log(func):        # 接受一个函数作为参数,并返回一个函数;
    def wrapper(*args,**kw):
        print("Call %s():" % func.__name__)
        return func(*args,**kw)
    return wrapper


# 借助Python的@语法,把decorator置于函数定义处
@log 
def time():
    print("One min.")
    
    
# 调用time函数
print("添加了log的time函数:")
time()
print("没有添加functoos.wrap的time.__name__:",time.__name__)
print("------------------------------------------------------------------")

# 1.time()  <===> time = log(time)

# 2.log()是一个decorator,返回一个函数,因此原来的time()函数仍然存在,
# 现在同名的time变量指向新的函数,调用time()将执行新函数,
# 即在log()函数中返回的wrapper()函数;

# 3.wrapper()函数的参数定义(*args,**kw),因此,wrapper()函数可以接受任意参数的调用,
# 在wrapper()函数内,先打印日志,再调用原始函数;

# 实例:自定义log的文本
def log(text):
    def decorator(func):
        def wrapper(*args,**kw):
            print("%s %s():" % (text,func.__name__))
            return func(*args,**kw)
        return wrapper
    return decorator


# 调用方法
@log("execute")
def date():
    print("Today is 2022-01-27.")
    
print("3层嵌套的decorator用法:")
date()
print("3层嵌套用法没有使用functools.wrap的date.__name__:",date.__name__)

# 1.date <======> log("execute")(date)
# 2.先执行log("execute"),返回decorator函数;
# 再调用返回的函数,参数是date函数,返回值最终是wrapper函数;
print("------------------------------------------------------------------")

# 把原始函数的__name__等属性复制到wrapper()函数,使用functools.wraps
# 在wrapper函数的前面添加@functools.wraps(func)
# 实例:
import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args,**kw):
        print("Call %s():" % func.__name__)
        return func(*args,**kw)
    return wrapper

@log
def date():
    print("今天是2022年1月27日.")
    
    
print("添加了functools处理的函数:",date.__name__)
date()
print("------------------------------------------------------------------")

# 带参数的decorator
import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args,**kw):
            print("%s %s():" % (text,func.__name__))
            return func(*args,**kw)
        return wrapper
    return decorator


@log("execute")
def moment():
    print("现在是上午10点39分.")
    
    
print("3层嵌套添加functools处理的函数:",moment.__name__)
moment()
# 结果输出:
通过变量调用函数:
1min.
通过name属性,得到函数的名字为: time
变量通过name属性,可以得到函数的名字: time
------------------------------------------------------------------
添加了log的time函数:
Call time():
One min.
没有添加functoos.wrap的time.__name__: wrapper
------------------------------------------------------------------
3层嵌套的decorator用法:
execute date():
Today is 2022-01-27.
3层嵌套用法没有使用functools.wrap的date.__name__: wrapper
------------------------------------------------------------------
添加了functools处理的函数: date
Call date():
今天是2022127.
------------------------------------------------------------------
3层嵌套添加functools处理的函数: moment
execute moment():
现在是上午1039.
# 启动AGV控制前打印一些控制指令提示log
import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args,**kw):
        print("AGV按键控制")
        print("----------W----------")
        print("------A-------D------")
        print("----------S----------\n")
        print("Description:\n")
        print("W按键实现前进")
        print("A按键实现左转")
        print("S按键实现后退")
        print("D按键实现右转\n")
        return func(*args,**kw)
    return wrapper


@log
def control():
    print("这是AGV控制程序测试.")
    
    
control()
# 结果输出:
AGV按键控制
----------W----------
------A-------D------
----------S----------

Description:

W按键实现前进
A按键实现左转
S按键实现后退
D按键实现右转

这是AGV控制程序测试.

2.偏函数

# 1.偏函数(Partial function)是functools模块提供的功能;
# 2.创建偏函数:functools.partial;
# 3.偏函数作用:把一个函数的某些参数固定住,即设置默认值,返回一个新的函数;
# 实例:
# int()函数可以把字符串转换为整数
numStr = "520"
numStr2 = "1010"
strToInt = int(numStr)

print("字符串原始内容为:",numStr)
print("字符串原始内容的类型为:",type(numStr))

print("字符串转换为整数为:",strToInt)
print("字符串转换后的类型为:",type(strToInt))
print("------------------------------------------")

# int()函数提供额外的base参数,默认值为10,如果传入base参数,实现做N进制的转换;
strTo2 = int(numStr2,base = 2)
strTo8 = int(numStr,base = 8)
strTo16 = int(numStr,base = 16)

print("'1010'按二进制转换:",strTo2)
print("'520'按八进制转换:",strTo8)
print("'520'按十六进制转换:",strTo16)
print("------------------------------------------")

# 实例:需要转换大量的二进制字符串,定义一个转换函数
def int2(x, base = 2):
    return int(x, base)


# 测试:
print("1111按二进制转换:",int2("1111"))
print("10101010按二进制转换:",int2("10101010"))
print("------------------------------------------")

# 使用functools.partial创建偏函数
import functools

int2 = functools.partial(int, base = 2)

print("'1111'使用偏函数按二进制转换的结果:",int2("1111"))
print("'10101010'使用偏函数按二机制转换的结果:",int2("10101010"))
print("'10101010'使用偏函数按十进制转换的结果:",int2("10101010",base = 10))
# 结果输出:
字符串原始内容为: 520
字符串原始内容的类型为: <class 'str'>
字符串转换为整数为: 520
字符串转换后的类型为: <class 'int'>
------------------------------------------
'1010'按二进制转换: 10
'520'按八进制转换: 336
'520'按十六进制转换: 1312
------------------------------------------
1111按二进制转换: 15
10101010按二进制转换: 170
------------------------------------------
'1111'使用偏函数按二进制转换的结果: 15
'10101010'使用偏函数按二机制转换的结果: 170
'10101010'使用偏函数按十进制转换的结果: 10101010
import functools

strInput = input("请输入您要转换的数字:")
exchange = input("请输入您要按照什么进制进行转换(2、8、10、16):")

int2 = functools.partial(int, base = 2)
int8 = functools.partial(int, base = 8)
int10 = functools.partial(int, base = 10)
int16 = functools.partial(int, base = 16)

if (exchange == "2"):
    print("按照二进制转换的结果为:",int2(strInput))
elif (exchange == "8"):
    print("按照八进制转换的结果为:",int8(strInput))
elif (exchange == "10"):
    print("按照十进制转换的结果为:",int10(strInput))
elif (exchange == "16"):
    print("按照十六进制转换的结果为:",int16(strInput))
else:
    print("输入不存在!")
    print("再见!")
# 结果输出:
请输入您要转换的数字:10101010
请输入您要按照什么进制进行转换(281016)2
按照二进制转换的结果为: 170
-----------------------------------------------
请输入您要转换的数字:1000
请输入您要按照什么进制进行转换(281016)8
按照八进制转换的结果为: 512
-----------------------------------------------
请输入您要转换的数字:584520
请输入您要按照什么进制进行转换(281016)10
按照十进制转换的结果为: 584520
-----------------------------------------------
请输入您要转换的数字:584520
请输入您要按照什么进制进行转换(281016)16
按照十六进制转换的结果为: 5784864
-----------------------------------------------
请输入您要转换的数字:584520
请输入您要按照什么进制进行转换(281016)9
输入不存在!
再见!
举报

相关推荐

0 条评论