鱼C论坛

 找回密码
 立即注册
查看: 1794|回复: 2

[已解决]函数修饰符

[复制链接]
发表于 2021-4-11 09:05:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
import time

def timeslong(func):
    def call():
        start = time.clock()
        print("It's time starting ! ")
        func()   #这句话什么作用啊?
        print("It's time ending ! ")
        end = time.clock()
        return "It's used : %s ." % (end - start)
    return call

@timeslong
def f():
    y = 0
    for i in range(10):
        y = y + i + 1
        print(y)
    return y

print(f())
                #这整块代码什么意思啊?
最佳答案
2021-4-11 11:22:54
本帖最后由 阿奇_o 于 2021-4-11 12:17 编辑

你们叫“修饰符”? 一般翻译为 装饰器 吧,毕竟 英文原词是 Decorator
Decorator 装饰器,本质是 函数的嵌套。 其特别在于,传递的是 所装饰/修饰下的那个函数对象。

理解的关键是:函数,竟然像 一个对象。函数也有“初始化”,函数初始化生成一个内存地址,和它真正被执行,是可以分开的!
# 1. 装饰器的本质是:函数嵌套。     外层函数返回 内层函数对象(内存地址),等待遇到小括号来执行。
def outer_func():
    def inner_func():
        print('Hi')
    return inner_func

in_f = outer_func()
print(in_f)
in_f()
in_f()

# 2. 装饰器,就像 一种包装、包裹,一种特殊的封装方法。
def decorator_func():
    print('--------------------')
    def wrapper_func():
        print('Hi, Hi.')
     # return ? 如果这里返回的是传入函数对象,会怎样呢?
    return wrapper_func

w_f = decorator_func()
w_f()
#继续扩展,如果 w_f 不叫 w_f,而是和 传入的函数对象名 同名呢?——这时,@decorator_func  就诞生了!


# 请看:
def my_decorator(decorated_func):
    # print('------- xxxx -------') #暂不要理会这句
    def wrapper_func(name, age):
        print('------- 我在这就 装 饰一下 -------')
        return decorated_func(name, age)
    return wrapper_func

# @my_decorator
def hi(name, age):
    print(f'Hi, 你好。我叫{name}, {age}岁。 交个朋友?')

# 1.
# 传入函数对象(参数暂不传入,因为参数需要加小括号,函数对象遇到小括号立马执行了,这里不是我们需要的)
decorated_func = my_decorator(decorated_func=hi) 
decorated_func('王大锤', 2333)

# 2.
# 若用上 @my_decorator 这一语法,就可以简化成:
# hi('王大锤', 2333) # 注:因为装饰器的“装饰”,该函数执行的逻辑 就不完全等于其本身的定义。

# 2.0
# 它实际上 等价于 下面两句
# hi = my_decorator(hi)     # 注意 要注释掉@my_decoratorn那句,不然print(装饰一下) 会 被执行两次,因为@my_decorator,相当于调用my_decorator(hi)
# hi('王大锤', 2333)



# 这样 以后 很方便地,只要你 @my_decorator 装饰下你自定义的函数,就可以 得到该装饰的附加效果。


# 典型应用,就是你代码想要实现的 计时功能(可看做是一种装饰),只要传入该函数对象 被@timelong 就可以被计时用时多久。
# 另一个典型应用是,触发写日记。 即创建一个专属的日记装饰器(如myLogger),再装饰和定义 一个日记信息函数(如 @myLogger  def web_login(user, ip): ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-4-11 09:40:41 | 显示全部楼层
import time

def timeslong(func):
    def call():
        start = time.perf_counter()
        print("It's time starting ! ")
        func()   #这句话什么作用啊?
        print("It's time ending ! ")
        end = time.perf_counter()
        return "It's used : %s ." % (end - start)
    return call

def f():
    y = 0
    for i in range(10):
        y = y + i + 1
        print(y)
    return y

print(timeslong(f)())

将代码修改成以上这样你能否看明白呢?

函数timeslong传入的参数是个函数,在内嵌函数call中被调用

在上面的函数中,通过@timeslong给原函数f()增加了计时的功能

python函数修饰符@的作用是为现有函数增加额外的功能,常用于插入日志、性能测试、事务处理等等。

创建函数修饰符的规则:
(1)修饰符是一个函数
(2)修饰符取被修饰函数为参数
(3)修饰符返回一个新函数
(4)修饰符维护被维护函数的签名
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-4-11 11:22:54 | 显示全部楼层    本楼为最佳答案   
本帖最后由 阿奇_o 于 2021-4-11 12:17 编辑

你们叫“修饰符”? 一般翻译为 装饰器 吧,毕竟 英文原词是 Decorator
Decorator 装饰器,本质是 函数的嵌套。 其特别在于,传递的是 所装饰/修饰下的那个函数对象。

理解的关键是:函数,竟然像 一个对象。函数也有“初始化”,函数初始化生成一个内存地址,和它真正被执行,是可以分开的!
# 1. 装饰器的本质是:函数嵌套。     外层函数返回 内层函数对象(内存地址),等待遇到小括号来执行。
def outer_func():
    def inner_func():
        print('Hi')
    return inner_func

in_f = outer_func()
print(in_f)
in_f()
in_f()

# 2. 装饰器,就像 一种包装、包裹,一种特殊的封装方法。
def decorator_func():
    print('--------------------')
    def wrapper_func():
        print('Hi, Hi.')
     # return ? 如果这里返回的是传入函数对象,会怎样呢?
    return wrapper_func

w_f = decorator_func()
w_f()
#继续扩展,如果 w_f 不叫 w_f,而是和 传入的函数对象名 同名呢?——这时,@decorator_func  就诞生了!


# 请看:
def my_decorator(decorated_func):
    # print('------- xxxx -------') #暂不要理会这句
    def wrapper_func(name, age):
        print('------- 我在这就 装 饰一下 -------')
        return decorated_func(name, age)
    return wrapper_func

# @my_decorator
def hi(name, age):
    print(f'Hi, 你好。我叫{name}, {age}岁。 交个朋友?')

# 1.
# 传入函数对象(参数暂不传入,因为参数需要加小括号,函数对象遇到小括号立马执行了,这里不是我们需要的)
decorated_func = my_decorator(decorated_func=hi) 
decorated_func('王大锤', 2333)

# 2.
# 若用上 @my_decorator 这一语法,就可以简化成:
# hi('王大锤', 2333) # 注:因为装饰器的“装饰”,该函数执行的逻辑 就不完全等于其本身的定义。

# 2.0
# 它实际上 等价于 下面两句
# hi = my_decorator(hi)     # 注意 要注释掉@my_decoratorn那句,不然print(装饰一下) 会 被执行两次,因为@my_decorator,相当于调用my_decorator(hi)
# hi('王大锤', 2333)



# 这样 以后 很方便地,只要你 @my_decorator 装饰下你自定义的函数,就可以 得到该装饰的附加效果。


# 典型应用,就是你代码想要实现的 计时功能(可看做是一种装饰),只要传入该函数对象 被@timelong 就可以被计时用时多久。
# 另一个典型应用是,触发写日记。 即创建一个专属的日记装饰器(如myLogger),再装饰和定义 一个日记信息函数(如 @myLogger  def web_login(user, ip): ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-16 02:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表